Jac*_*son 5 cocoa-touch image uiimage nsoperationqueue imageview
我正在尝试编写一个从URL加载图像的iPad应用程序.我使用以下图像加载代码:
url = [NSURL URLWithString:theURLString];
NSData *data = [NSData dataWithContentsOfURL:url];
img = [[UIImage alloc] initWithData:data];
[imageView setImage:img];
[img release];
NSLog(@"Image reloaded");
Run Code Online (Sandbox Code Playgroud)
所有这些代码都作为操作添加到NSOperationQueue中,因此它将异步加载,如果图像的websever很慢,则不会导致我的应用程序锁定.我添加了NSLog行,因此我可以在控制台中看到此代码执行完毕后.
我一直注意到在代码完成执行后大约5秒钟,我的应用程序中的图像会更新.但是如果我自己使用这个代码而不将它放在NSOperationQUeue中,它似乎几乎立即更新了图像.
滞后不是完全由缓慢的Web服务器引起的...我可以在Safari中加载图像URL并且加载时间不到一秒,或者我可以使用相同的代码加载它而不使用NSOperationQueue并且加载速度更快.
有没有办法在我的图像显示之前减少滞后但是继续使用NSOperationQueue?
根据文档,您编写的代码无效.UIKit对象可能不会在主线程上的任何地方调用.我敢打赌,你正在做的事情恰好在大多数方面都有效,但是没有成功地改变显示,屏幕由于其他原因而巧合地更新.
Apple强烈建议,如果您希望保持电池效率,则线程不是执行异步URL提取的方法.相反,您应该使用NSURLConnection并允许runloop组织异步行为.编写一个快速的方法,只是将数据累积到NSData并不难,因为它会在连接完成后将整个事情发布给代理,但假设你更愿意坚持你已经得到的东西我建议:
url = [NSURL URLWithString:theURLString];
NSData *data = [NSData dataWithContentsOfURL:url];
[self performSelectorOnMainThread:@selector(setImageViewImage:) withObject:data waitUntilDone:YES];
...
- (void)setImageViewImage:(NSData *)data
{
img = [[UIImage alloc] initWithData:data];
[imageView setImage:img];
[img release];
NSLog(@"Image reloaded");
}
Run Code Online (Sandbox Code Playgroud)
performSelectorOnMainThread按照名称所说的 - 发送到的对象将在运行循环到达时将主对象上作为单个参数给出的对象调度请求的选择器.在这种情况下,'data'是NSOperation隐式创建的线程中池上的自动释放对象.因为你需要它才能保持有效直到它被使用,我已经习惯了waitUntilDone:YES.另一种方法是使数据成为您明确拥有的东西并让主线程方法释放它.
这种方法的主要缺点是,如果图像以压缩形式(例如JPEG或PNG)返回,则它将在主线程上解压缩.为了避免这种情况,如果没有对UIImage的行为进行经验猜测,超出所记录的安全性,你需要降低到C级并使用CoreGraphics.但我认为这样做超出了这个问题的范围.