在Xcode 11 beta 5或6中,我依赖URLSession.DataTaskPublisher
的现有代码停止工作。似乎DataTaskPublisher
从未发布过任何值,但我不知道为什么。
我尝试将.sink
和.handleEvents
作为订阅者。我已经与Just
发布者测试了.sink,并确认它在那里接收了一个值。
我还尝试了给DataTaskPublisher
一个URL
并给它一个URLRequest
。我尝试了对包含授权标头的API的请求,以及对google.com和apple.com的基本请求。我尝试使用URLSession.shared
并创建URLSession
的新实例。我也尝试过使用和不使用map
和decode
运算符。
我使用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)
})
}
该项目打印“视图已加载”,但没有其他任何打印。关于我在哪里出错的任何想法吗?谢谢!
答案 0 :(得分:2)
我认为您的代码有两个问题,首先,您只有发布者(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参数接收器,因为发布者的错误并非从不。最后,print()仅用于测试,并且效果很好。
答案 1 :(得分:0)
更改
URLSession.shared.dataTaskPublisher...
到
let _ = URLSession.shared.dataTaskPublisher...
现在,发布者已被保留,并有机会做一些事情。