如何从主线程设置注释视图的图像

时间:2012-12-19 22:01:57

标签: objective-c multithreading annotations mapkit

我有一个从Flicker下载图像的应用程序(Xcode 4.5)。我有一个mapview,它会删除每张照片的位置。单击该图钉会显示一个注释,其中显示了照片的名称和图像的缩略图。一切都工作正常,直到我决定从主线程下载缩略图(我第一次尝试多线程)。使用我目前拥有的代码,注释不再显示缩略图。

我已经设置了4种方法来执行此任务。第四种方法甚至没有被调用。我希望有人可以查看这段代码并指出明显的错误和/或尝试这种方法的不同方式:

在我的mapview控制器类中:

//an annotation was selected
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)aView
{
self.currentAnnotationView = [[MKAnnotationView alloc]init];
self.currentAnnotationView = aView;
[self.delegate mapViewController:self 
    imageForAnnotation:self.currentAnnotationView.annotation];
}

使用委托,上面的方法在我的tableview控制器类中调用以下内容:

// downloads Flickr image
- (void )mapViewController:(MapViewController *)sender imageForAnnotation:    
      (id<MKAnnotation>)annotation
{      
FlickrPhotoAnnotation *fpa = (FlickrPhotoAnnotation *)annotation;

dispatch_queue_t downloadQueue = dispatch_queue_create("flickr annotation image  
       downloader", NULL);
dispatch_async(downloadQueue, ^{
    NSURL *url = [FlickrFetcher urlForPhoto:fpa.photo format:FlickrPhotoFormatSquare]; 
    NSData *data = [NSData dataWithContentsOfURL:url];
    self.thumbnailImage = [UIImage imageWithData:data];
        dispatch_async(dispatch_get_main_queue(), ^ {
            MapViewController *mvc = [[MapViewController alloc]init];
            [mvc setAnnotationImage];  
        });
    });
}

上述方法通过mapview控制器类的实例调用以下消息:

//gets thumbnail image and sets it to the annotation view
 - (void)setAnnotationImage
 {
 UIImage *image = [self.delegate getThumbnailImage];
 [(UIImageView *)self.currentAnnotationView.leftCalloutAccessoryView setImage:image];
 }    

最后,上面的方法使用委托在表视图控制器类中调用下面的方法(没有被调用 - 不知道为什么):

//returns the thumbnail image acquired in download
 - (UIImage *)getThumbnailImage;
 {
    return self.thumbnailImage;
 }  

1 个答案:

答案 0 :(得分:1)

不会调用该方法,因为您没有设置第二个mapViewController的委托:

dispatch_async(dispatch_get_main_queue(), ^ {
            MapViewController *mvc = [[MapViewController alloc]init];
            [mvc setAnnotationImage];  
            [mvc setDelegate:self];
        });

应该是:

dispatch_async(dispatch_get_main_queue(), ^ {
            MapViewController *mvc = [[MapViewController alloc]init];
            [mvc setDelegate:self];
            [mvc setAnnotationImage];  
        });

...但你不应该制作一个新的mapViewController,你应该在现有的 mapViewController(发送者)上设置注释图像。

dispatch_async(dispatch_get_main_queue(), ^ {
            [sender setAnnotationImage];  
        });

...并且在调用setAnnotationImage时,你也可以传入UIImage(当你传递消息时有这些信息),避免了最后一个委托回调的需要:

更改setAnnotationImage方法以接收图像:

- (void)setAnnotationImage:(UIImage*)image
 {
 [self.currentAnnotationView.leftCalloutAccessoryView setImage:image];
 }  

然后你可以一次性设置它:

dispatch_async(dispatch_get_main_queue(), ^ {
            [sender setAnnotationImage:self.thumbnailImage];  
        });

...而self.thumbnailImage可能不需要是iVar,如果这是你需要得到它的唯一地方......