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 out dataimageURL 전달 된 있고 그 중 누구도 비어 있습니다.

제안 사항?

답변

2

dispatch_async을 호출하면 나중에 해당 작업을 예약 할 수 있습니다. 작업이 끝나기 전에 함수가 nil로 종료됩니다. 함수에 콜백 블록을 추가하거나 이미지 데이터를 받고 처리 할 때까지 블록을 차단할 수 있습니다.

다음은 블록 콜백이있는 함수의 예와 사용 방법입니다.

- (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; 
    }); 
}];