0

我有一個URL,當它被複制到瀏覽器中時,它顯示一個圖像。我的功能應該是異步下載圖像。使用大中央調度下載UIImage

- (UIImage *)downloadImage:(NSString *)imageURL 
{ 
    NSError *error = nil; 
    NSURL *urlString = [NSURL URLWithString:imageURL]; 
    NSData *data = [NSData dataWithContentsOfURL:urlString options:NSDataReadingUncached error:&error]; 
    __block UIImage *image; 

    if (!error) { 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
     dispatch_async(queue, ^{ 
      image = [UIImage imageWithData:data]; 
     }); 
     return image; 
    } else { 
     NSLog(@"%@", [error localizedDescription]); 
    } 
    return nil; 
} 

當我嘗試顯示在UIImageView形象我沒有得到任何錯誤,什麼都沒有。我已經NSLogged出dataimageURL通過,並沒有一個是空的。

有什麼建議嗎?

回答

2

通過致電dispatch_async,您可以安排該工作稍後進行。在完成該工作之前,您的函數將以零結束。您需要爲您的功能添加回調塊,或者在您接收並處理圖像數據之前將其阻止。

下面是一個帶回調塊的函數示例以及如何使用它。

- (void)downloadImageAtURL:(NSString *)imageURL withHandler:(void(^)(UIImage *image))handler 
{ 
    NSURL *urlString = [NSURL URLWithString:imageURL]; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(queue, ^{ 
     NSError *error = nil; 
     NSData *data = [NSData dataWithContentsOfURL:urlString options:NSDataReadingUncached error:&error]; 
     if (!error) { 
      UIImage *downloadedImage = [UIImage imageWithData:data]; 
      handler(downloadedImage); // pass back the image in a block 
     } else { 
      NSLog(@"%@", [error localizedDescription]); 
      handler(nil); // pass back nil in the block 
     } 
    }); 
} 



- (void)keyboardDidShow:(NSNotification *)aNotification { 
    [self downloadImageAtURL:@"" withHandler:^(UIImage *image) { 
     if (image) { 
      // display 
     } else { 
      // handle probelm 
     } 
    }]; 
} 
+0

好眼力。我會做出必要的調整:) –

+0

您可能想要返回錯誤(如果有的話),如其他人的答案中所示。 – MJN

+0

此外,你應該檢查NSURLSession和下載任務。使用'dataFromURL',您將所有圖像數據加載到內存中,這可能會導致問題(圖像很大)。 – MJN

2

到dataWithContentsOfURL呼叫:選擇:錯誤:需要是dispatch_queue塊內爲它是異步的。對UI的任何更改都需要位於mainThread中。它應該看起來像這樣:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
    dispatch_async(queue, ^(void) { 

     NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; 

     UIImage* image = [[UIImage alloc] initWithData:imageData]; 
     if (image) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
        //load image into UIImageView 
       } 
      }); 
     } 
    }); 
1

您不是異步下載圖像。此外,應該以異步方式返回值的方法無法通過方法返回值返回該值,但應使用塊返回該值。

你可以嘗試做這樣的事情:

- (void)downloadImage:(NSString *)imageURL onComplete:(void (^)(UIImage *, NSError * error))onComplete 
{ 
    NSURL *urlString = [NSURL URLWithString:imageURL]; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(queue, ^{ 
     NSError *error = nil; 
     NSData *data = [NSData dataWithContentsOfURL:urlString options:NSDataReadingUncached error:&error]; 
     image = [UIImage imageWithData:data]; 
     if (onComplete) { 
      // Keep in mind that onComplete block will be called on a background thread. 
      // If you need to use it on UIImageView, you must set it on main thread. 
      onComplete(image, error); 
     }    
    }); 
} 

然後,當你需要設置UIImageView的圖像:

__weak typeof(self)selfB = self; // Better to use a weak reference inside blocks to avoid retain cycles 
[self downloadImage:myURLString onComplete:^(UIImage * image, NSError * error) { 
    dispatch_async(dispatch_get_main_queue(), ^{ // As you can see, we use main thread for UI updates 
     selfB.imageView.image = image; 
    }); 
}];