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

无法子类化URLSessionDataTask?如何为其添加关联属性?

关于子类化URLSessionDataTask的解决方案

核心结论:无法直接子类化URLSessionDataTask

苹果设计URLSession任务体系时,采用了封闭的工厂模式——所有URLSessionDataTask实例都是由URLSession内部创建返回的,开发者既不能直接实例化自定义子类,也无法让URLSession生成我们自己定义的子类实例。你写的URLSessionDataTask_Plus子类根本无法被URLSession调用生成实例,所以这条路走不通。

替代方案:用关联对象给系统任务动态附加属性

这是最接近你需求的实现方式,不需要额外包装类,直接给原生URLSessionDataTask添加存储进度观察的属性:

import ObjectiveC

// 定义关联对象的唯一标识
private var ProgressObservationKey = 0

extension URLSessionDataTask {
    // 给系统任务动态添加progressObservation属性
    var progressObservation: NSKeyValueObservation? {
        get {
            objc_getAssociatedObject(self, &ProgressObservationKey) as? NSKeyValueObservation
        }
        set {
            objc_setAssociatedObject(self, &ProgressObservationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

使用示例:

let url = URL(string: "https://example.com/large-file")!
let task = URLSession.shared.dataTask(with: url)

// 绑定进度观察并直接存在task对象上
task.progressObservation = task.progress.observe(\.fractionCompleted) { progress, _ in
    DispatchQueue.main.async {
        print("当前进度:\(progress.fractionCompleted * 100)%")
    }
}

task.resume()

进阶优化:封装任务创建逻辑

如果不想每次手动处理观察绑定,可以给URLSession写扩展,把逻辑封装起来:

extension URLSession {
    func dataTask(with url: URL, progressHandler: @escaping (Double) -> Void) -> URLSessionDataTask {
        let task = dataTask(with: url)
        let observation = task.progress.observe(\.fractionCompleted) { progress, _ in
            DispatchQueue.main.async {
                progressHandler(progress.fractionCompleted)
            }
        }
        task.progressObservation = observation
        return task
    }
}

使用时更简洁:

let task = URLSession.shared.dataTask(with: url) { progress in
    print("进度更新:\(progress*100)%")
}
task.resume()

注意事项

  • 关联对象会和task对象绑定生命周期:task被释放时,关联的NSKeyValueObservation也会自动释放,无需手动管理销毁。
  • 如果需要提前终止观察,直接设置task.progressObservation = nil即可。

内容的提问来源于stack exchange,提问作者Fattie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 05:41:03