操作员使用调度程序后,iOS13的合并流不会流动

时间:2019-07-12 16:07:24

标签: swift ios13 combine

在操作员使用调度程序后,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

但是实际输出什么也没有。

如果我不使用receivethrottledebouncedelay。输出会很好。

这是错误还是我的代码有问题?

我尝试过Playground(Xcode 11 beta3)。

2 个答案:

答案 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被释放后立即被取消。

我的猜测是,如果将其放在另一个线程上,那么当调用方法的末尾到达时,可取消操作将在收到订阅之前取消分配。但是,当在当前线程上接收到该消息时,它似乎正在及时执行以显示订阅和输出。当前线程退出时,很有可能取消了取消状态。