在iOS中使用线程返回图像
嗨,我正在通过斯坦福大学iOS开发课。 我有一个关于线程的问题。 我知道UIKit调用应该由主线程来处理。 我想知道这样的事情是否合法?
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id<MKAnnotation>)annotation { FlickrPhotoAnnotation *fpa = (FlickrPhotoAnnotation *) annotation; NSURL *url = [FlickrFetcher urlForPhoto:fpa.photo format:FlickrPhotoFormatSquare]; __block UIImage *image; dispatch_queue_t downloadQ = dispatch_queue_create("download queue", NULL); dispatch_async(downloadQ, ^{ NSData *data = [NSData dataWithContentsOfURL:url]; if (data) { dispatch_async(dispatch_get_main_queue(), ^{ image = [UIImage imageWithData:data]; }); } }); dispatch_release(downloadQ); return image; }
或者我应该返回NSData并处理调用方法中的所有线程?
谢谢
你的代码不会做你想要的。
您正在将asynchronous块放入队列,然后立即从该方法返回。 你不能保证在你返回之前这个块会实际运行 – 事实上,它的可能性是不会的。
所以你会返回image
的当前值。 既然你没有初始化它,可能是垃圾。 无论谁调用这个方法,都会尝试使用一个垃圾指针指向一个图像,并且(如果你幸运的话)会崩溃。 如果你初始化为零:
__block UIImage *image = nil;
那会更有礼貌一点。
这里的问题是:你的方法必须返回一个UIImage
,所以你必须等待的时间来做一个完整的UIImage
在你返回之前。 在其他线程上这样做没有任何好处 – 您仍然在等待相同的时间,切换线程只会增加开销。
为了以有效的asynchronous方式加载图像,需要通过callback委托方法或块的方式asynchronous告诉调用者何时加载图像。 例如,查看Foundation中的NSURLConnection
。 它有一个较老的方法,通过一个委托来callback,而一个更新的方法( +sendAsynchronousRequest:queue:completionHandler:
通过一个块callback。
我同意CodaFi的评论。 其实,图像可以创build主线程。 UIView创build和操作必须在主线程上完成,但是UIImage不是UIView。 此外,运行时可能会给你一个警告或错误,如果你试图操纵显示在另一个线程的UI(当我不小心更新另一个线程上的UITableView)。