gpt4 book ai didi

iphone - 返回使用 GCD 在单独线程中检索到的值

转载 作者:行者123 更新时间:2023-12-01 18:30:59 25 4
gpt4 key购买 nike

我编写了一个自定义 View Controller 类,它显示带有注释的 map 。按下注释时,会显示一个标注,并且在注释标注的左侧会显示一个缩略图。此类要求委托(delegate)人提供显示的图像。

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
[(UIImageView *)view.leftCalloutAccessoryView setImage:[self.delegate mapViewController:self imageForAnnotation:view.annotation]];
}

委托(delegate)类从网络中检索图像。为了防止 UI 无响应,创建了一个新线程来使用 GCD 下载图像。
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id<MKAnnotation>)annotation
{
NSURL *someURL = [[NSURL alloc] initWithString:@"a URL to data on a network"];
__block UIImage *image = [[UIImage alloc] init];

dispatch_queue_t downloader = dispatch_queue_create("image downloader", NULL);
dispatch_async(downloader, ^{
NSData *imageData = [NSData dataWithContentsOfURL:someURL]; // This call can block the main UI!
image = [UIImage imageWithData:imageData];
});

return image;
}

为什么图像从不显示?我假设由于委托(delegate)方法返回一个指向图像的指针,该图像在 future 的某个时间被设置为缩略图最终会自行更新的有效图像数据。这显然不是这样的......

最佳答案

您正在创建一个异步执行的 block 。这意味着您的代码创建了要执行的 block ,然后立即返回“图像”,它指向您在初始化变量时创建的新图像:__block UIImage *image = [[UIImage alloc] init];请记住,当您从一个方法返回一个对象时,您实际上只是返回了一个指向该对象的指针。

在返回指向这个新图像的指针之后的某个时间。该 block 运行并将指向它检索到的图像的指针分配给局部变量“图像”,该变量现在超出了该方法的范围(尽管该 block 仍然具有它)。因此,现在该 block 具有对它获得的图像的此引用,但是当该 block 完成时该引用将消失。

解决此问题的一种方法是同步运行该 block ,但这会破坏分派(dispatch)图像检索过程的意义。您需要做的是为检索到图像后可以调用的函数提供一个 block ,即将图像分配到需要的位置。这看起来像这样:

- (void)mapViewController:(MapViewController *)sender imageForAnnotation:(id<MKAnnotation>)annotation withImageBlock:(void (^)(UIImage *))block{
{
NSURL *someURL = [[NSURL alloc] initWithString:@"a URL to data on a network"];
__block UIImage *image = [[UIImage alloc] init];

dispatch__object_t currentContext = dispatch_get_current_queue();
dispatch_queue_t downloader = dispatch_queue_create("image downloader", NULL);
dispatch_async(downloader, ^{
NSData *imageData = [NSData dataWithContentsOfURL:someURL]; // This call can block the main UI!
image = [UIImage imageWithData:imageData];
dispatch_async(currentContext, ^{
block(image);
});
});
}

请注意,我获取了当前队列上下文,以便可以在给我的同一个线程上执行给我的 block 。这非常重要,因为传递给我的 block 可能包含 UIKit 方法,这些方法只能在主线程上执行。

关于iphone - 返回使用 GCD 在单独线程中检索到的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8857146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com