为什么 URLSession.DataTaskPublisher 从不发布值?
Why doesn't URLSession.DataTaskPublisher ever publish values?
在 Xcode 11 beta 5 或 6 中,我现有的依赖 URLSession.DataTaskPublisher
的代码停止工作。似乎 DataTaskPublisher
从未发布任何值,但我不知道为什么。
我试过 .sink
和 .handleEvents
作为订阅者。我已经通过 Just
发布商测试了 .sink 并确认它在那里收到了一个值。
我也试过给 DataTaskPublisher
一个 URL
和 URLRequest
。我尝试了 API 的请求,包括授权 header,以及 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)
})
}
该项目打印 "view did load" 但没有其他打印。关于我在这里哪里出错的任何想法?谢谢!
我认为您的代码有两个问题,首先您只有一个发布者(handleEvent returns 一个发布者),其次发布者超出范围并消失了。尽管它并不十分优雅,但它确实有效。
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 = [=10=].data; response = [=10=].response }
)
}
struct ContentView: View {
var body: some View {
Button(
action: { combineTest() },
label: { Text("Do It").font(.largeTitle) }
)
}
}
我是在 SwiftUI 中完成的,这样我就不用担心了,而且我使用了 3 个变量,这样我就可以更好地跟进。您需要使用 2 参数接收器,因为发布者的错误不是从不。最后 print() 仅用于测试,效果非常好。
在 Xcode 11 beta 5 或 6 中,我现有的依赖 URLSession.DataTaskPublisher
的代码停止工作。似乎 DataTaskPublisher
从未发布任何值,但我不知道为什么。
我试过 .sink
和 .handleEvents
作为订阅者。我已经通过 Just
发布商测试了 .sink 并确认它在那里收到了一个值。
我也试过给 DataTaskPublisher
一个 URL
和 URLRequest
。我尝试了 API 的请求,包括授权 header,以及 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)
})
}
该项目打印 "view did load" 但没有其他打印。关于我在这里哪里出错的任何想法?谢谢!
我认为您的代码有两个问题,首先您只有一个发布者(handleEvent returns 一个发布者),其次发布者超出范围并消失了。尽管它并不十分优雅,但它确实有效。
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 = [=10=].data; response = [=10=].response }
)
}
struct ContentView: View {
var body: some View {
Button(
action: { combineTest() },
label: { Text("Do It").font(.largeTitle) }
)
}
}
我是在 SwiftUI 中完成的,这样我就不用担心了,而且我使用了 3 个变量,这样我就可以更好地跟进。您需要使用 2 参数接收器,因为发布者的错误不是从不。最后 print() 仅用于测试,效果非常好。