私は iOS 5.0 開発に関する優れた CS193P レクチャーに従っています:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
私は今、割り当て #5、必要なタスク #5b に取り組んでいます。マップ上の注釈をクリックしたときに、サムネイルを含む吹き出しを表示する必要があります。
次のコード(Flickrを使用)で問題なくこれを行うことができました。
MapViewController.h:
@class MapViewController;
@protocol MapViewControllerDelegate <NSObject>
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id <MKAnnotation>)annotation;
@end
@interface MapViewController : UIViewController
@property (nonatomic, strong) NSArray *annotations; // of id <MKAnnotation>
@property (nonatomic, weak) id <MapViewControllerDelegate> delegate;
@end
MapViewController.m:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)annotationView
{
if ([annotationView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
UIImage *image = [self.delegate mapViewController:self imageForAnnotation:annotationView.annotation];
[(UIImageView *)annotationView.leftCalloutAccessoryView setImage:image];
}
}
PhotoListTableViewController.m:
@interface PhotoListTableViewController() <MapViewControllerDelegate>
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id <MKAnnotation>)annotation
{
UIImage *image = nil;
if ([annotation isKindOfClass:[FlickrAnnotation class]]) { // make sure the annotation is a FlickrAnnotation
FlickrAnnotation *flickrAnnotation = (FlickrAnnotation *)annotation;
NSURL *photoUrl = [FlickrFetcher urlForPhoto:flickrAnnotation.photo format:FlickrPhotoFormatSquare];
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
}
return image;
}
@end
MapViewController の mapView:didSelectAnnotationView: メソッドでデリゲートを使用して、別のコントローラー PhotoListTableViewController から画像を取得します (汎用の MapViewController があることを確認するため)。
正常に動作しています... しかし、別のスレッドで Flickr を呼び出すには、このコードを変更する必要があります。そこで、mapViewController:imageForAnnotation: メソッドを次のように変更しました。
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id <MKAnnotation>)annotation
{
__block UIImage *image = nil;
if ([annotation isKindOfClass:[FlickrAnnotation class]]) { // make sure the annotation is a FlickrAnnotation
FlickrAnnotation *flickrAnnotation = (FlickrAnnotation *)annotation;
dispatch_queue_t downloadQueue = dispatch_queue_create("ThumbnailDownloader", NULL);
dispatch_async(downloadQueue, ^{
NSURL *photoUrl = [FlickrFetcher urlForPhoto:flickrAnnotation.photo format:FlickrPhotoFormatSquare];
dispatch_async(dispatch_get_main_queue(), ^{ // execute on the main thread
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
});
});
dispatch_release(downloadQueue);
}
return image;
}
ただし、このコードではサムネイルは表示されません。メソッドが「画像を返す」場合、画像はまだnilであり、downloadQueueスレッドが完了していないためです。次のように、ブロック内で「画像を返す」ことを試みました。
return [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
しかし、コンパイラはそれを好まない:
'UIImage *(^)(void)' をタイプ 'disptach_block_t' (別名 'void (^)(void)') のパラメーターに渡す互換性のないブロック ポインター タイプ
ブロックの先頭にある ^{ は void を意味することはわかっていますが、UIImage を返すように変更できますか? それとも最初からやり方が悪いのでしょうか?
PhotoListTableViewController から MapViewController に画像を返す方法がわかりません。これはどのように行うべきですか?