iOS13 的组合流在使用调度程序的操作员之后不流动

kum*_*one 6 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)")
    })
Run Code Online (Sandbox Code Playgroud)

我预计输出是

1
2
finished
Run Code Online (Sandbox Code Playgroud)

但实际输出什么也没有。

如果我不使用receiveorthrottledebounceor delay. 输出会很好。

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

我尝试使用 Playground(Xcode 11 beta3)。

kej*_*eji 4

订阅:

我不确定为什么它在单线程的情况下工作,但你应该确保received(subscription:)调用subscriber. 如果您不需要处理订阅者的需求,您可以使用Subscribers.empty

struct MyPublisher: Publisher {

    typealias Output = Int
    typealias Failure = Never

    func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
        subscriber.receive(subscription: Subscriptions.empty)
        _ = subscriber.receive(1)
        Swift.print("called 1")
        _ = subscriber.receive(2)
        Swift.print("called 2")
        _ = subscriber.receive(completion: .finished)
        Swift.print("called finish")
    }
}
Run Code Online (Sandbox Code Playgroud)

任何可取消的:

您应该注意到一个警告:

调用“sink(receiveCompletion:receiveValue:)”的结果未使用

这应该会出现,因为sink返回一个AnyCancellable

func sink(receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) -> AnyCancellable
Run Code Online (Sandbox Code Playgroud)

一旦被释放,任何返回 an 的东西AnyCancellable都会被取消AnyCancellable

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