在操作员使用调度程序后,iOS13的合并发布者流似乎没有流动。
这是我的代码:
import Foundation
import Combine
struct MyPublisher: Publisher {
typealias Output = Int
typealias Failure = Error
func receive<S>(subscriber: S) where S : Subscriber,
Failure == S.Failure,
Output == S.Input {
subscriber.receive(1)
print("called 1")
subscriber.receive(2)
print("called 2")
subscriber.receive(completion: .finished)
print("called finish")
}
}
MyPublisher()
// .receive(on: RunLoop.main) // If this line removed, it will be fine.
// .throttle(for: .milliseconds(1000), scheduler: RunLoop.main, latest: false)) // If this line removed, it will be fine.
// .debounce(for: .milliseconds(1000), scheduler: RunLoop.main)) // If this line removed, it will be fine.
// .delay(for: .milliseconds(1000), scheduler: DispatchQueue.main)) // If this line removed, it will be fine.
.print()
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("finished")
case .failure(let error):
print("error:\(error)")
}
}, receiveValue: { num in
print("\(num)")
})
我希望输出是
1
2
finished
但是实际输出什么也没有。
如果我不使用receive
或throttle
或debounce
或delay
。输出会很好。
这是错误还是我的代码有问题?
我尝试过Playground(Xcode 11 beta3)。
答案 0 :(得分:2)
使用可取消
例如:
class ImageLoader: ObservableObject {
@Published var image: UIImage?
private var cancellable: AnyCancellable?
func fetchImages() {
guard let urlString = urlString,
let url = URL(string: urlString) else { return }
cancellable = URLSession.shared.dataTaskPublisher(for: url)
.map { UIImage(data: $0.data) }
.replaceError(with: nil)
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.image = $0 }
}
}
答案 1 :(得分:1)
您应该注意到一个警告:
'sink(receiveCompletion:receiveValue :)'的调用结果未使用
应该出现,因为sink
返回了AnyCancellable
:
func sink(receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) -> AnyCancellable
返回AnyCancellable
的所有内容将在AnyCancellable
被释放后立即被取消。
我的猜测是,如果将其放在另一个线程上,那么当调用方法的末尾到达时,可取消操作将在收到订阅之前取消分配。但是,当在当前线程上接收到该消息时,它似乎正在及时执行以显示订阅和输出。当前线程退出时,很有可能取消了取消状态。