Как заглушить URLSession в Swift?
Я следовал этому уроку, чтобы заглушить 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 ответ
Я наконец нашел решение. Это восхитительно, так как мы скучали по дереву за деревьями. Есть две проблемы:
1) Кажется, что Swift 4 изменил подпись для dataTask(with: NSURLRequest)
в dataTask(with: URLRequest)
Поэтому строка в моем первом вопросе будет соответствовать только сигнатуре протокола, и она никогда не попадет в dataTask
внутри URLSession
отсюда и бесконечный цикл. Чтобы решить эту проблему, мне пришлось изменить 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, гораздо проще издеваться надURLProtocol
который URLSession
используется для отправки запроса.