iOS(cs193p):使用MapViewController中的委托来使用与另一个控制器不同的线程获取图像的问题

时间:2013-01-25 22:22:45

标签: ios xcode cs193p

我正在关注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

我在mapView中使用了一个委托:didSelectAnnotationView:MapViewController的方法从另一个控制器中检索图像,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;
}

但是,使用此代码时,不会显示缩略图。我知道这是因为当方法“返回图像”时,图像仍为零,导致downloadQueue线程尚未完成。我尝试在块内“返回图像”,如下所示:

return [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];

但是编译器不喜欢这样:

  

不兼容的块指针类型将'UIImage *(^)(void)'传递给   'disptach_block_t'类型的参数(又名'void(^)(void)')

我知道^ {在块的开头意味着无效,但可以更改为返回UIImage吗?或者我从一开始就做错了吗?

我只是不知道如何将PhotoListTableViewController中的图像返回给MapViewController。该怎么做?

1 个答案:

答案 0 :(得分:2)

我正在做同样的任务。我在调用tableview控制器委托时切换了线程,而不是等到表视图控制器获取图像,这对我有效。

在代码中:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)视图 {    // 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];

    });

});

}