在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)。