URLSession.shared.dataTaskPublisher在IOS 13.3上不起作用

时间:2019-12-11 06:14:34

标签: swift swiftui combine ios13.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 个答案:

答案 0 :(得分:3)

您没有显示足够的代码,但是根据症状,您可以清楚地知道问题所在:发布者/订阅者对象的生存时间不够长。我敢说您的代码总是错误的,这似乎是成功的怪癖。确保您的发布者(尤其是您的订阅者)保留在长期存在的对象(例如实例属性)中,以便有时间进行网络通信。

这是一个如何使用数据任务发布者的可行示例:

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(仅是本地用户)已经不存在了立即,网络交易会被过早取消(有您报告的错误)。

答案 1 :(得分:3)

您在这里有2个问题: 1.就像@matt所说,您的发布者的寿命不足。您可以将AnyCancellable存储为实例var,或者我想做的(似乎是redux的最佳实践)是将store(in:)应用于Set<AnyCancellable>保留它,并在释放对象时自动清除它。 2.为了启动实际的网络请求,您需要sinkassign值。

因此,将它们放在一起:

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)
}

答案 2 :(得分:0)

我需要将可取消集“移动”到我的订户正在执行的功能范围之上。当可取消集的范围与订阅者的功能相同,但在iOS 13.2中停止工作时,此方法在iOS 13.2中工作正常。 dataTaskPublisher因以上错误而取消。可以取消的设置应该使订户“存活”是有意义的。开发人员错误。学过的知识。