子类化URLSession遇iOS13弃用警告,如何改用sessionWithConfiguration?
解决URLSession子类初始化的废弃警告问题
你在创建Mock URLSession的子类时遇到了如下警告:
'init()' was deprecated in iOS 13.0: Please use +[NSURLSession sessionWithConfiguration:] or other class methods to create instances
下面针对这个问题给出两种解决方案,优先推荐协议抽象的方式,更符合Swift的设计原则:
方案一:协议抽象(更优解)
直接子类化URLSession会受限于其初始化规则,改用协议定义网络请求接口,既能避开废弃警告,又能让Mock实现更灵活。
- 定义网络请求协议
protocol NetworkSession { func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask }
- 让系统URLSession遵守该协议
extension URLSession: NetworkSession {}
- 实现Mock类
class WeatherURLSessionFake: NetworkSession { var data: Data? var response: URLResponse? var error: Error? init(data: Data?, response: URLResponse?, error: Error?) { self.data = data self.response = response self.error = error } func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { let task = WeatherURLSessionDataTaskFake() task.completionHandler = completionHandler task.data = data task.urlResponse = response task.responseError = error return task } func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { let task = WeatherURLSessionDataTaskFake() task.completionHandler = completionHandler task.data = data task.urlResponse = response task.responseError = error return task } }
后续业务代码依赖NetworkSession协议即可,轻松切换真实URLSession和Mock实例。
方案二:子类化URLSession(兼容原有思路)
如果坚持要子类化,需要重写父类的指定初始化器,并用类方法创建实例,避免调用废弃的无参初始化器:
class WeatherURLSessionFake: URLSession { var data: Data? var response: URLResponse? var error: Error? // 用类方法创建Mock实例,内部调用父类的配置初始化器 static func fakeSession(data: Data?, response: URLResponse?, error: Error?) -> WeatherURLSessionFake { let config = URLSessionConfiguration.default let session = self.init(configuration: config) as! WeatherURLSessionFake session.data = data session.response = response session.error = error return session } // 重写父类指定初始化器,避开废弃的init() override init(configuration: URLSessionConfiguration, delegate: URLSessionDelegate? = nil, delegateQueue: OperationQueue? = nil) { super.init(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue) } // 必须实现废弃的init(),但标记为不推荐使用 @available(*, deprecated, message: "请使用fakeSession(data:response:error:)创建实例") override init() { super.init() } override func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { let task = WeatherURLSessionDataTaskFake() task.completionHandler = completionHandler task.data = data task.urlResponse = response task.responseError = error return task } override func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { let task = WeatherURLSessionDataTaskFake() task.completionHandler = completionHandler task.data = data task.urlResponse = response task.responseError = error return task } }
使用时通过WeatherURLSessionFake.fakeSession(data:..., response:..., error:...)创建实例即可消除警告。
内容的提问来源于stack exchange,提问作者jmz49
相关产品推荐
相关产品推荐

