2014-01-14 4 views
1

NSOperation 및 완료 블록을 사용하여 원격 웹 이미지를 가져 오려고합니다. 본질적으로 수신 객체 (뷰 컨트롤러)는 SGImageManager의 fetchImageWithUrlString : completionBlock 메소드를 호출하며, 이는 완료 블록을 가진 SGFetchImageOperation을 설정합니다. 결국, 작업은 완료 블록 내에서 완료 블록을 호출합니다.iOS에서 중첩 완료 블록과 함께 NSOperation을 사용하면 반복되는 EXC_BAD_ACCESS가 발생합니다.

응용 프로그램이 충돌하지 않지만 표시된 줄에서 반복적으로 중단되며 관리자는 operationImage 및 operationUrlString과 관련된 이상한 값이 있습니다. 이 디버깅하는 방법을 모르겠습니다. 내가 가진 유일한 이론은 어떤 이유로 순환 호출이 발생했다는 것입니다.

//SGFetchImageOperation.h 
typedef void(^SGFetchImageCompletionBlock)(UIImage *image, NSString *urlString); 

@interface SGFetchImageOperation : NSOperation 
@property (nonatomic, strong) NSString *urlString; 
@property (copy) SGFetchImageCompletionBlock completionBlock; 
@end 


//SGFetchImageOperation.m 
#import "SGFetchImageOperation.h" 

@implementation SGFetchImageOperation 

- (void)main { 
    @autoreleasepool { 
     if (self.isCancelled) { 
      return; 
     } 

     UIImage *image = [self image]; 

     if (self.isCancelled) { 
      return; 
     } 

     if(self.completionBlock && self.urlString && image) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       self.completionBlock(image, self.urlString); 
      }); 
     } 
    } 
} 

- (UIImage *)image{ 
    UIImage *image; 
    if(self.urlString){ 
     NSURL *url = [NSURL URLWithString:self.urlString]; 
     NSError *error = nil; 
     NSData *data = [NSData dataWithContentsOfURL:url options:NSDataReadingMappedAlways error:&error]; 
     if (data) { 
      image = [UIImage imageWithData:data]; 
     } else { 
      NSLog(@"Error downloading image. %@", error.localizedDescription); 
     } 
    } 
    return image; 
} 

@end 



//SGImageManager.h 
#import "SGFetchImageOperation.h" 

@interface SGImageManager : NSObject 
- (void)fetchImageWithUrlString:(NSString *)urlString completionBlock:(SGFetchImageCompletionBlock)completionBlock; 
@end 


//SGImageManager.m 
- (void)fetchImageWithUrlString:(NSString *)urlString completionBlock:(SGFetchImageCompletionBlock)completionBlock { 
    SGFetchImageOperation *operation = [SGFetchImageOperation new]; 
    operation.urlString = urlString; 

    //Keeps breaking on this line with "Thread x: EXC_BAD_ACCESS (code=2, address=0x1)", but doesn't seem to crash. 
    operation.completionBlock = ^(UIImage *operationImage, NSString *operationUrlString){ 

     completionBlock(operationImage, operationUrlString); 
    }; 
    [self.queue addOperation:operation]; 
} 
+0

매우 먼저 같은 것을 당신의 현재 속성의 이름을 바꿀 수있는, 블록 자체의 사용이 잘못 자기에 약한 포인터를 만들고, 다른 현명한 사이클을 유지 만듭니다 .. .? –

+0

앱이 충돌하고 한 지점에서 깨지 않는 경우 ..! 중단 점이 없다고 확신합니까? 어떤 시점에서 앱을 깨고 재생 버튼을 누른 후 다시 실행을 시작합니까? –

답변

3

나는 여기에 문제가 이미 completionBlock에 대해 정의 된 메소드가 NSOperation의 서브 클래스에 completionBlock라는 속성을 추가하고 생각합니다.

하위 클래스의 속성을 없애고 NSOperation의 -setCompletionBlock: 메서드를 사용할 수 있습니다.

또는, 당신은 내가 말하고 싶은 SGCompletionBlock