我想要一个Subject(类似于CurrentValueSubject)我可以发布到,但这验证了我发送的值。例如,我想验证输入是否强制在一系列值之间,例如 1 和 10。如果高于最大值,则通过最大值,如果低于最小值,则通过最小值。
请不要告诉我在订阅代码上过滤结果,因为这是我试图避免的。那个重复。
伪代码将是:
let intSubject = ValidatedValueSubject<Int>(value: 5, min: 1, max: 10)
intSubject.sink { value in print(value) }
intSubject.send(-10)
intSubject.send(5)
intSubject.send(15)
Run Code Online (Sandbox Code Playgroud)
我希望这样产生:
5
1
5
10
Run Code Online (Sandbox Code Playgroud)
显然用CurrentValueSubject我无法达到那种效果。我尝试创建自己的自定义主题,但似乎无法使其正常工作。
有人告诉我我应该以不同的方式看待我的问题,因为我想这太容易了,不需要自定义Subject.
用例:
我有一个设置类,它会在“设置”屏幕和其他任何地方更新,当值发生变化时,我希望屏幕做出相应的反应。在ValidatedValueSubject此设置中生活对象。
设置需要公开,Subject以便任何屏幕都可以对属性的更改做出反应。
我的习惯做法Subject如下:
5
1
5
10
Run Code Online (Sandbox Code Playgroud)
你可以包装一个CurrentValueSubject:
class MySubject<Output, Failure: Error>: Subject {
init(initialValue: Output, groom: @escaping (Output) -> Output) {
self.wrapped = .init(groom(initialValue))
self.groom = groom
}
func send(_ value: Output) {
wrapped.send(groom(value))
}
func send(completion: Subscribers.Completion<Failure>) {
wrapped.send(completion: completion)
}
func send(subscription: Subscription) {
wrapped.send(subscription: subscription)
}
func receive<Downstream: Subscriber>(subscriber: Downstream) where Failure == Downstream.Failure, Output == Downstream.Input {
wrapped.subscribe(subscriber)
}
private let wrapped: CurrentValueSubject<Output, Failure>
private let groom: (Output) -> Output
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
let subject = MySubject<Int, Never>(initialValue: 5) { max(1, min($0, 10)) }
let ticket = subject.sink { print("value: \($0)") }
subject.send(-10)
subject.send(5)
subject.send(15)
Run Code Online (Sandbox Code Playgroud)
输出:
class MySubject<Output, Failure: Error>: Subject {
init(initialValue: Output, groom: @escaping (Output) -> Output) {
self.wrapped = .init(groom(initialValue))
self.groom = groom
}
func send(_ value: Output) {
wrapped.send(groom(value))
}
func send(completion: Subscribers.Completion<Failure>) {
wrapped.send(completion: completion)
}
func send(subscription: Subscription) {
wrapped.send(subscription: subscription)
}
func receive<Downstream: Subscriber>(subscriber: Downstream) where Failure == Downstream.Failure, Output == Downstream.Input {
wrapped.subscribe(subscriber)
}
private let wrapped: CurrentValueSubject<Output, Failure>
private let groom: (Output) -> Output
}
Run Code Online (Sandbox Code Playgroud)