【问题标题】:URLSession.shared.dataTaskPublisher not working on IOS 13.3URLSession.shared.dataTaskPublisher 在 IOS 13.3 上不起作用
【发布时间】:2019-12-11 06:14:34
【问题描述】:

尝试发出网络请求时,出现错误

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。

【问题讨论】:

    标签: swift swiftui combine ios13.3


    【解决方案1】:

    这里有两个问题: 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)
    }
    

    【讨论】:

    • 我不明白为什么这里需要 .store。 RxSwift 有更清晰和有意义的语法。合并需要更多改进。
    • 因为发布者超出范围,否则会立即解除分配。 RxSwift 没有bag 的概念吗?同样的交易。
    【解决方案2】:

    您没有显示足够的代码,但根据症状很清楚问题出在哪里:您的发布者/订阅者对象的生存时间不够长。我敢说你的代码总是错的,它似乎成功只是一个怪癖。确保您的发布者,尤其是您的订阅者保留在长期对象中,例如实例属性,以便网络通信有时间进行。

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

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

    打印&lt;UIImage:0x6000008ba490 anonymous {180, 206}&gt;,这是正确的(您可以通过自己访问该 URL 看到)。

    我的意思是,如果你不说self.sub = sub,你就会得到你所报告的错误:订阅者sub,它只是一个本地的,立即不存在并且网络交易被提前取消(您报告的错误)。

    EDIT 我认为代码是在.store(in:) 方法存在之前编写的;如果我今天写它,我会使用它而不是 sub 属性。但原理是一样的。

    【讨论】:

      【解决方案3】:

      我需要将我的可取消集移动到订阅者正在执行的函数范围的“上方”。当可取消集与订阅者的功能具有相同的范围时,这在 iOS 13.2 中运行良好,但在 13.3 中停止工作。 dataTaskPublisher 因上述错误而取消。可取消集应该“活”订户是有道理的。开发者错误。学过的知识。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-19
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 2016-07-03
        • 2012-05-29
        • 2015-07-15
        相关资源
        最近更新 更多