hfhbd
(Hfhbd)
1
Hey,
I want to request https://swift.org. If I do not assign the result of the publisher/subject sink(receiveCompletion:receiveValue:) of type AnyCancellable, the request will not executed.
Do you know if this behaviour is correct? Or does the compiler removes this code?
import SwiftUI
import Combine
struct ContentView: View {
@ObservedObject private var viewModel = ViewModel()
var body: some View {
Form {
Text(self.viewModel.content)
Text(self.viewModel.output)
Button("noVar") {
self.viewModel.noVar()
}
Button("variable") {
self.viewModel.variable()
}
}
}
}
final class ViewModel: ObservableObject {
@Published var content = "Loading swift.org"
@Published var output = "no output"
private var cancellable: AnyCancellable! = nil
func noVar() {
self.output = "noVar start"
_ = URLSession.shared.dataTaskPublisher(for: URL(string: "https://swift.org")!) //never called
.receive(on: RunLoop.main)
.tryMap { (data, response) in
self.output = "_gotRespond"
let result = String(data: data, encoding: .utf8)!
print(result) // no print
self.output = "_isOnline \(result)"
return result
}
.mapError { error -> Error in
self.output = error.localizedDescription
return error
}
.sink { completion in
switch completion {
case .failure(let error):
self.output = error.localizedDescription
case .finished:
self.output = "noVar ends"
}
} receiveValue: {
self.content = $0
}
}
func variable() {
self.output = "variable"
self.cancellable = URLSession.shared.dataTaskPublisher(for: URL(string: "https://swift.org")!)
.receive(on: RunLoop.main)
.tryMap { (data, response) in
self.output = "v_gotRespond"
let result = String(data: data, encoding: .utf8)!
print(result)
self.output = "v_isOnline \(result)"
return result
}
.mapError { error -> Error in
self.output = error.localizedDescription
return error
}
.replaceError(with: "v_Error printed")
.assign(to: \.content, on: self)
}
deinit {
print("canceling")
self.cancellable.cancel()
}
}
1 Like
Jon_Shier
(Jon Shier)
2
This is expected behavior. The lifetime of the cancellation token controls the lifetime of the observation and underlying work, like the network request.
2 Likes
hfhbd
(Hfhbd)
3
Thank you! I think, maybe this behaviour was changed, because my old code, created 2019 with Combine (iOS 13) does not execute the publisher anymore... But now, the reason why is clear and logically.
Jon_Shier
(Jon Shier)
4
This behavior is racy between the cancellation of the token once it's deinitd and the completion of the network request, so I would expect differing behavior through a variety of variables.