【问题标题】:In iOS, using NSOperation with nested completion block results in repeated EXC_BAD_ACCESS在 iOS 中,使用带有嵌套完成块的 NSOperation 会导致重复的 EXC_BAD_ACCESS
【发布时间】:2014-01-14 13:38:05
【问题描述】:

我正在尝试使用 NSOperation 和完成块获取远程 Web 图像。本质上,接收对象(视图控制器)将调用 SGImageManager 的 fetchImageWithUrlString:completionBlock 方法,该方法又会设置一个具有自己的完成块的 SGFetchImageOperation。最后,该操作调用完成块内的完成块。

应用程序没有崩溃,但它在指示的行上反复中断,并且在检查器中,存在与 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];
}

【问题讨论】:

  • 首先我想说的是,在块中使用 self 是错误的,创建指向 self 的弱指针,否则会创建保留循环...?
  • 如果应用程序没有崩溃和中断..!你确定没有断点?哪个使应用程序中断并在点击播放按钮后再次开始运行?

标签: ios objective-c objective-c-blocks nsoperation


【解决方案1】:

我认为这里的问题是您将一个名为 completionBlock 的属性添加到 NSOperation 的子类中,该子类已经为 completionBlock 定义了方法。

你可以去掉子类的属性,只使用 NSOperation 的-setCompletionBlock: 方法。

或者,您可以将当前属性重命名为 SGCompletionBlock

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多