7

在 Xcode 11 beta 5 或 6 中,我依赖的现有代码URLSession.DataTaskPublisher停止工作。似乎DataTaskPublisher从未发布任何值,但我不知道为什么。

我已经尝试过.sink.handleEvents作为订阅者。我已经与发布者一起测试了 .sinkJust并确认它在那里收到了一个值。

我也尝试过给DataTaskPublisheraURL和给它 a URLRequest。我尝试了对 API 的请求,包括授权标头,以及对 google.com 和 apple.com 的基本请求。我已经尝试使用URLSession.shared并创建一个新的URLSession. 我也尝试过使用和不使用mapanddecode运算符。

我已经使用XCTest期望来确认测试每次都会超时,即使我给它一个 4 分钟的超时时间。

我刚刚创建了一个新的示例项目,并在根视图控制器中使用以下代码复制了问题:

override func viewDidLoad() {
        super.viewDidLoad()

        print("view did load")

        URLSession.shared.dataTaskPublisher(for: URL(string: "http://apple.com")!)
            .handleEvents(receiveSubscription: { (sub) in
                print(sub)
            }, receiveOutput: { (response) in
                print(response)
            }, receiveCompletion: { (completion) in
                print(completion)
            }, receiveCancel: {
                print("cancel")
            }, receiveRequest: { (demand) in
                print(demand)
            })
    }

该项目打印“视图确实加载”但没有其他任何打印。关于我在哪里出错的任何想法?谢谢!

4

1 回答 1

8

我认为您的代码存在两个问题,首先您只有一个发布者(handleEvent 返回一个发布者),其次该发布者超出范围并消失了。尽管它并不完全优雅,但这很有效。


import Combine
import SwiftUI

var pub: AnyPublisher<(data: Data, response: URLResponse), URLError>? = nil
var sub: Cancellable? = nil

var data: Data? = nil
var response: URLResponse? = nil

func combineTest() {
    guard let url = URL(string: "https://apple.com") else {
        return
    }
    pub = URLSession.shared.dataTaskPublisher(for: url)
            .print("Test")
            .eraseToAnyPublisher()
    sub = pub?.sink(
        receiveCompletion: { completion in
            switch completion {
            case .finished:
                break
            case .failure(let error):
                fatalError(error.localizedDescription)
            }
        },
        receiveValue: { data = $0.data; response = $0.response }
    )
}

struct ContentView: View {
    var body: some View {
        Button(
            action: { combineTest() },
            label: { Text("Do It").font(.largeTitle) }
        )
    }
}

我是在 SwiftUI 中完成的,这样我就不用担心了,我使用了 3 个变量以便我可以更好地遵循。您需要使用 2 参数接收器,因为发布者的错误不是 Never。最后 print() 仅用于测试并且效果很好。

于 2019-09-01T06:48:44.770 回答