我一直在遵循本教程以示出URLSession
。该示例是通过创建协议并扩展现有URLSession
的来完成的示例。
protocol URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
func dataTask(with request: NSURLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
extension URLSession: URLSessionProtocol {
func dataTask(with request: NSURLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
return dataTask(with: request, completionHandler: completionHandler) as URLSessionDataTaskProtocol
}
}
单元测试按预期工作。但是,当我尝试运行真实的东西时,urlsession-> dataTask((进入无限循环并崩溃。似乎DataTask((正在呼唤自己。
我要忽略什么?
更新:
protocol URLSessionDataTaskProtocol {
var originalRequest: URLRequest? { get }
func resume()
}
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
我终于找到了解决方案。当我们错过了树木的木头时,这令人着迷。有两个问题:
1(似乎Swift 4将dataTask(with: NSURLRequest)
的签名更改为dataTask(with: URLRequest)
因此,我的开头问题中的行只能与协议的func签名相匹配,并且它永远不会在URLSession
内部击中dataTask
,因此无限循环。要解决此问题,我必须将NSURLRequest
更改为URLRequest
并相应地重构代码。
2(签名保持模糊,因此最好将结果存储为DataTask首先使用URLSessionDataTask
的铸件,然后返回变量。
Swift 4的新重构代码:
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
protocol URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
extension URLSession: URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
let task:URLSessionDataTask = dataTask(with: request, completionHandler: {
(data:Data?, response:URLResponse?, error:Error?) in completionHandler(data,response,error) }) as URLSessionDataTask
return task
}
}
我还发现我必须将URLSession.shared
注射为单身人士,而不是URLSession()
,否则可能会崩溃。
来到这里以了解如何模拟URLSession
诸如URLSessionDataTask
之类的任务?
大约swift 5,更易于模拟URLSession
使用的URLProtocol
来发送请求。
请参阅使用URLProtocol的单元测试。