URLSession.shared.dataTaskPublisher не работает на IOS 13.3
При попытке сделать сетевой запрос выдает сообщение об ошибке
finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled"
Если я использую URLSession.shared.dataTask
вместо того URLSession.shared.dataTaskPublisher
он будет работать на iOS 13.3.
Вот мой код:
return URLSession.shared.dataTaskPublisher(for : request).map{ a in
return a.data
}
.decode(type: MyResponse.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
Этот код работал на IOS 13.2.3.
3 ответа
У вас есть 2 проблемы:
1. как сказал @matt, ваш издатель живет недостаточно долго. Вы можете сохранитьAnyCancellable
как пример var
, или то, что мне нравится делать (и кажется, что это лучшая практика сокращения), - это использовать store(in:)
к Set<AnyCancellable>
чтобы он оставался поблизости и автоматически очищался, когда объект освобождается. 2. Чтобы запустить фактический сетевой запрос, вам необходимоsink
или assign
Значение.
Итак, собрав их вместе:
var cancellableSet: Set<AnyCancellable> = []
func getMyResponse() {
URLSession.shared.dataTaskPublisher(for : request).map{ a in
return a.data
}
.decode(type: MyResponse.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.replaceError(with: MyResponse())
.sink { myResponse in print(myResponse) }
.store(in: &cancellableSet)
}
Вы не показали достаточно кода, но по симптому становится ясно, в чем проблема: ваши объекты издателя / подписчика живут недостаточно долго. Рискну сказать, что ваш код всегда был неправильным, и то, что он казался успешным, было просто странностью. Убедитесь, что ваш издатель и особенно ваш подписчик сохранены в долгоживущих объектах, таких как свойства экземпляра, чтобы у сетевого взаимодействия было время.
Вот рабочий пример того, как использовать издателя задач данных:
class ViewController: UIViewController {
let url = URL(string:"https://apeth.com/pep/manny.jpg")!
lazy var pub = URLSession.shared.dataTaskPublisher(for: url)
.compactMap {UIImage(data: $0.data)}
.receive(on: DispatchQueue.main)
var sub : AnyCancellable?
override func viewDidLoad() {
super.viewDidLoad()
let sub = pub.sink(receiveCompletion: {_ in}, receiveValue: {print($0)})
self.sub = sub
}
}
Это печатает <UIImage:0x6000008ba490 anonymous {180, 206}>
, что правильно (как вы сами можете убедиться, перейдя по этому URL-адресу).
Я хочу сказать, что если вы не скажете self.sub = sub
, вы получите именно ту ошибку, о которой сообщаете: подписчик sub
, который является просто локальным, немедленно прекращает свое существование, а сетевая транзакция преждевременно отменяется (с указанной вами ошибкой).
ИЗМЕНИТЬ Я думаю, что этот код был написан до.store(in:)
метод существовал; если бы я писал это сегодня, я бы использовал это вместоsub
свойство. Но принцип тот же.
Мне нужно было переместить отменяемый набор "выше" области действия функции, которую выполнял мой подписчик. Это нормально работало в iOS 13.2, когда отменяемый набор имел ту же область действия, что и функция подписчика, но перестал работать в 13.3. DataTaskPublisher отменяется с ошибкой, указанной выше. Имеет смысл, что отменяемый набор должен "выходить из строя" абонента. Ошибка разработчика. Урок выучен.