1

私は 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 に画像を返す方法がわかりません。これはどのように行うべきですか?

4

1 に答える 1

2

私は同じ任務に取り組んでいます。テーブルビューコントローラーが画像をフェッチするまで待つのではなく、テーブルビューコントローラーデリゲートが呼び出されたときにスレッドを切り替えました。これは私にとってはうまくいきます。

コード内:

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { // NSLog(@"注釈を選択、サムネイルを取得");

dispatch_queue_t downloadQueue = dispatch_queue_create("flickr download", NULL);
dispatch_async(downloadQueue, ^{
    UIImage *image = [self.delegate thumbNailImageForAnnotation:view.annotation sender: self];

    dispatch_async(dispatch_get_main_queue(), ^{

        [(UIImageView *)view.leftCalloutAccessoryView setImage:image];

    });

});

}

于 2013-01-26T18:38:51.233 に答える