2012-08-23 4 views
2

NSDocumentDirectory에서 여러 개의 uiimageview async로 이미지를 읽어야 UI가 차단되지 않습니다. 백그라운드에서 perform selector를 사용하여 uiimage를로드 할 수 있다는 것을 알고 있지만 어떻게 동적 uiimageview와 연관시킬 수 있습니까?비동기 문서의 이미지

답변

4

한 편리한 방법은 블록 같은 것을 사용하는 것입니다. 백그라운드 스레드에서 이미지를 압축 해제하는 것도 좋은 생각입니다. 따라서 이미지를 처음 사용할 때 주 스레드가이를 수행 할 필요가 없습니다.

#import <UIKit/UIKit.h> 


@interface UIImage (Decode) 

- (UIImage *)decodedImage; 

@end 

있는 UIImage

있는 UIImage + Decode.h : 여기

typedef void (^MBLoaderCompletion)(UIImage *image); 

가 해제 코드를 구현하는 UIImage 카테고리이다 :로

- (void)loadFullImageAt:(NSString *)imageFilePath completion:(MBLoaderCompletion)completion { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
     NSData *imageData = [NSData dataWithContentsOfFile:imageFilePath]; 
     UIImage *image = nil; 
     if (imageData) { 
      image = [[[UIImage alloc] initWithData:imageData] decodedImage]; 
     } 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      completion(image); 
     }); 
    }); 
} 

콜백이 정의되고 + 12 월 ode.m

#import "UIImage+Decode.h" 


@implementation UIImage (Decode) 

- (UIImage *)decodedImage { 
    CGImageRef imageRef = self.CGImage; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(NULL, 
               CGImageGetWidth(imageRef), 
               CGImageGetHeight(imageRef), 
               8, 
               // Just always return width * 4 will be enough 
               CGImageGetWidth(imageRef) * 4, 
               // System only supports RGB, set explicitly 
               colorSpace, 
               // Makes system don't need to do extra conversion when displayed. 
               kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); 
    CGColorSpaceRelease(colorSpace); 
    if (!context) return nil; 

    CGRect rect = (CGRect){CGPointZero,{CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}}; 
    CGContextDrawImage(context, rect, imageRef); 
    CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 

    UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef scale:self.scale orientation:self.imageOrientation]; 
    CGImageRelease(decompressedImageRef); 
    return decompressedImage; 
} 

@end 

여기에 제공된 샘플 코드는 우리가 ARC를 사용하고 있다고 가정합니다.

+0

끔찍한 답변입니다. 감사! –

+0

이것은 훌륭한 대답입니다. 취소 메커니즘을 추가하기 위해이를 수정할 수 있습니까? –

1

UIImageView-s를 만들 수있는 스레드를 생성하고 이미지를로드 할 수있는 NSThread/dispatch queue를 사용할 수 있습니다.

2

"동적"UIImageView라고 할 때, 프로그래밍 방식으로 UIScrollView에 이러한 것들이 생성되어 있습니까? UITableView에? samfisher는 기본적인 질문에 매우 옳았습니다. 그러나 세부 사항은 UIImageView를 작성한 방법에 따라 약간 다릅니다 (예 : UITableView의 경우 셀이 계속 표시되고 대기열에서 제외되지 않았는지 확인해야 함, UIScrollView, 이미지가 여전히 화면에 표시되는 경우에만 UIImageView를로드 할 수 있습니다 (이미지가 크거나 많은 경우에는 esp).

하지만 기본적인 아이디어는 같은 것을 할 수 있다는 것입니다 : 당신은 어떤 배경 대기열 또는 스레드에서 이미지의 검색을 호출

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    UIImage *image = [self getTheImage]; 

    // ok, now that you have the image, dispatch the update of the UI back to the main queue 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     // if the image view is still visible, update it 

    }); 

}); 

참고하지만 주에 다시 UI를 업데이트해야합니다 실!

스크롤보기를 업데이트하는 경우 고려중인 here 또는 here과 같이보기가 계속 표시되는지 확인하고 싶을 수 있습니다. 만약 당신이 테이블 뷰를 업데이트하고 있다면, 아마도 셀이 여전히 보이는지를 확인하는 this과 같은 것일 겁니다. 그것은 모두 당신이하려고하는 것에 달려 있습니다. (- 처음 액세스를 UIImage 그렇지 않으면 이미지 데이터가 연기로드 때문에)

[self loadFullImageAt:imagePath completion:^(UIIMage * image){ 
    self.imageView.image = image; 
}]; 

당신이 데이터로 이미지를로드합니다 :

관련 문제