Вы создаете блок, который выполняется асинхронно. Это означает, что ваш код создал блок для выполнения, а затем сразу же возвратил «изображение», которое указывало на новое изображение, которое вы создали при инициализации переменной: __block UIImage *image = [[UIImage alloc] init];
Помните, что когда вы возвращаете объект из метода, вы на самом деле просто возвращаете указатель на этот объект.
Через некоторое время после возвращения указателя на это новое изображение. Блок запускается и назначает указатель на изображение, которое он получил, на локальную переменную 'image', которая теперь выходит за рамки метода (хотя блок все еще имеет ее). Так что теперь у блока есть эта ссылка на полученное изображение, но эта ссылка исчезнет, когда блок завершится.
Одним из способов решения этой проблемы является синхронный запуск блока, но это будет препятствовать отправке процесса поиска изображения. Что вам нужно сделать, так это предоставить блок функции, которую он может вызвать после получения изображения, а именно назначить изображение там, где оно должно быть. Это будет выглядеть примерно так:
- (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);
});
});
}
Обратите внимание, что я получаю текущий контекст очереди, чтобы выполнить блок, переданный мне в том же потоке, что и мне. Это действительно важно, поскольку переданный мне блок может содержать методы UIKit, которые могут выполняться только в основном потоке.