You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSOperation集成NSURLSessionDownloadTask取消操作时崩溃问题

崩溃根因

  1. 代码中使用__unsafe_unretained修饰weakSelf,该修饰符修饰的对象被释放后指针不会自动置为nil,会保留原内存地址成为野指针,回调触发后访问野指针直接抛出EXC_BAD_ACCESS错误。
  2. NSURLSession的任务回调会被session实例持有,你使用的sharedSession是全局单例,生命周期和应用一致,所以即便DownloadOperation对象被释放,任务完成/取消时回调仍然会触发,触发后访问野指针就会崩溃。

修复步骤

1. 替换内存修饰符,增加空判断

将initWithSession方法中的__unsafe_unretained替换为__weak,并在回调内部先尝试强持有对象,判断非空再执行后续逻辑:

- (instancetype)initWithSession:(NSURLSession *)session downloadTaskURL:(NSURL *)downloadTaskURL completionHandler:(nullable void (^)(NSURL * _Nullable,  NSURLResponse * _Nullable,  NSError * _Nullable))completionHandler {
    self = [super init];
    if (self) {
        // 替换为__weak,对象释放后自动置nil
        __weak DownloadOperation *weakSelf = self;
        _task = [[NSURLSession sharedSession] downloadTaskWithURL:downloadTaskURL
                                                completionHandler:^(NSURL * _Nullable localURL, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            // 内部强持有,避免执行过程中对象被释放
            __strong DownloadOperation *strongSelf = weakSelf;
            // 对象已经释放,直接返回避免野指针访问,可选继续执行外部传入的completionHandler
            if (completionHandler) {
                completionHandler(localURL, response, error);
            }
            if (!strongSelf) {
                return;
            }
            strongSelf.state = kFinished;
        }];
    }
    return self;
}

2. 可选优化(适配操作依赖)

当前你重写了isReady方法直接返回自定义状态,会丢失NSOperation默认的依赖支持,如果你的业务需要用到操作依赖,可以修改isReady的实现:

- (BOOL)isReady { 
    return [super isReady] && (self.state == kReady); 
}

内容的提问来源于stack exchange,提问作者Petter Sjölund

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:15:05