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];
}
매우 먼저 같은 것을 당신의 현재 속성의 이름을 바꿀 수있는, 블록 자체의 사용이 잘못 자기에 약한 포인터를 만들고, 다른 현명한 사이클을 유지 만듭니다 .. .? –
앱이 충돌하고 한 지점에서 깨지 않는 경우 ..! 중단 점이 없다고 확신합니까? 어떤 시점에서 앱을 깨고 재생 버튼을 누른 후 다시 실행을 시작합니까? –