我想在屏幕上显示我从互联网上获取的图像。我用过 NSURLConnection 创建异步调用以获取数据,在响应 block 中,我调用代码将其分配给 UIImage 对象。
我的问题是为什么我需要在 block 执行后调用 sleep(1)?如果我不调用它,那么我的图像就不会绘制在屏幕上。这是实现此目标的另一种更优雅的方法吗?
-(void)loadImage:(NSString *)url
{
NSURL *imageURL = [NSURL URLWithString:url];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0f];
[NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if(!connectionError) {
if(data) {
//there goes the main thingy
self.myView.wallpaperImage = [UIImage imageWithData:data];
[self.myView setNeedsDisplay];
} else {
NSLog(@"No data found at url:%@",url);
}
} else {
NSLog(@"Could not connect to %@",url);
}
}];
sleep(1);
}
最佳答案
这个:
self.myView.wallpaperImage = [UIImage imageWithData:data];
[self.myView setNeedsDisplay];
发生在由传递给 sendAsynchronousRequest 的 NSOperationQueue 管理的线程上。这些方法需要从主线程调用。 您的 sleep 可能导致主线程的 runloop 迭代,之后这些调用似乎起作用了。 要解决此问题并避免您当前的方法会遇到的一大堆其他问题,请执行以下操作:
[NSURLConnection sendAsynchronousRequest:imageRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if([data length] > 0) {
//there goes the main thingy
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.myView.wallpaperImage = [UIImage imageWithData:data];
[self.myView setNeedsDisplay];
}];
} else {
// Perform your error handling here.
}
}];
这将使用 [NSOperationQueue mainQueue]
从主队列执行那些 UIKit 调用 - 而不是 libdispatch。 libdispatch 是一个低级接口(interface),推荐的最佳做法是始终首选更高级别的接口(interface)——在本例中为 NSOperationQueue。 UIKit 只有在从主线程(或队列)调用时才是安全的。
它还会更改您的错误处理行为以遵循 best practices对于 platform - 检查您的调用结果(在本例中为数据),然后处理返回的任何错误。
您的代码实际上很好地说明了为什么 block 会保留捕获的对象(在本例中为 self)。如果这里没有保留循环,ARC 可以在 queue
超出范围时立即销毁它,并且该 block 将永远不会执行。相反,由于保留周期,队列会一直保留到 block 执行为止。
关于iOS:为什么我需要在 NSURLConnection sendAsynchronousRequest 之后使用 sleep(1)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24296038/