Как вернуть переменную из блока внутри метода?

Скажем, у меня есть этот метод, который с учетом URL-адреса возвращает UIImage:

- (void)getUIImageFromURL:(NSURL *)URL {
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    AFHTTPRequestOperation *imageOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    imageOperation.responseSerializer = [AFImageResponseSerializer serializer];

    [imageOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        return (UIImage *)responseObject;
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    }];

    [imageOperation start];
}

Но он продолжает выдавать мне эту ошибку:

Несовместимые типы указателей блоков отправляют "UIImage *(^)(AFHTTPRequestOperation *__strong, _strong id)" в параметр типа "void (^)(AFHTTPRequestOperation *_strong, __strong id)"

Я немного новичок в блоках, поэтому, возможно, я подхожу к этому совершенно наоборот. Как лучше всего реализовать такой метод?


person Doug Smith    schedule 07.12.2013    source источник


Ответы (3)


Вы не можете вернуть изображение из блока. Это асинхронный API, и его нельзя использовать так, как вы пытаетесь. Либо используйте блокирующий API, где метод блокируется до загрузки изображения (плохое решение), либо реализуйте поддержку асинхронного API. Например, передайте блок завершения вашему методу getImage и вызовите его в блоке завершения операции загрузки. В этом блоке делайте с изображением то, что вам нужно.

person Leo Natan    schedule 07.12.2013
comment
@AaronBrager Да, я в курсе. Я имел в виду, что он не может вернуть значение из блока вызывающей стороне внешней функции. - person Leo Natan; 07.12.2013
comment
Я был бы еще больше сбит с толку, если бы он пытался это сделать... так как внешняя функция также возвращает void. - person Aaron Brager; 07.12.2013

Блок обратного вызова в setCompletionBlockWithSuccess: является пустым блоком, вы не можете изменить его возвращаемый тип.

В вашем случае вы, вероятно, установили бы изображение внутри своего блока вместо того, чтобы возвращать изображение.

[imageOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    self.myImage.image = [UIImage imageWithData:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];

Однако если вы имеете дело с AFNetworking и изображениями, существуют методы категорий, которые должны значительно упростить извлечение и кэширование.

[self.myImage setImagewithURL:URL];
person Erik Kerber    schedule 07.12.2013
comment
В вашем ответе self.image должно быть self.myImage (категория находится в UIImageView, а не в UIImage). - person Aaron Brager; 07.12.2013
comment
@AaronBrager Поддельный код;). self.image должен был быть UIImageView. - person Erik Kerber; 07.12.2013

Вы вызываете асинхронный метод с двумя блоками для обработки успеха и неудачи. К моменту вызова одного из этих обработчиков ваш вызывающий метод уже давно устарел. Нет никакого смысла думать, что вы можете вернуть ему данные, потому что их больше нет.

В блоке успеха и блоке отказа вы даете инструкции, что делать в случае успешного или неудачного выполнения операции. Там некому что-то возвращать. Что вы делаете, так это добавляете код в блок для обработки и сохранения результата успеха в нужном месте или для правильной обработки ошибок.

person gnasher729    schedule 11.03.2014