Swift中能否为CustomPublisher类定义Setter实现直接赋值?
问题:如何让CustomPublisher支持直接赋值替代send方法
我实现了一个类似@Published的不可完成版CurrentValueSubject(CustomPublisher类),现在想不用调用.send(value),而是通过定义Setter,实现直接用customPublisher = newValue的方式完成赋值,请问这可行吗?
原调用方式:
customPublisher.send(newValue)
目标调用方式:
customPublisher = newValue
原自定义类代码:
final class CustomPublisher<Output: Any>: Publisher { typealias Failure = Never var value: Output private var wrapper: CurrentValueSubject<Output, Failure> init(_ value: Output) { self.value = value wrapper = .init(value) } func send(_ value: Output) { self.value = value wrapper.send(value) } func send(subscription: Subscription) { wrapper.send(subscription: subscription) } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { wrapper.receive(subscriber: subscriber) } }
解决方案
直接通过customPublisher = newValue的语法触发原实例的send逻辑不可行,因为CustomPublisher是类(引用类型),这种赋值操作会直接替换整个实例的引用,而非修改现有实例的内部状态。不过可以通过以下几种方式实现类似的简洁赋值效果:
方式一:利用value属性的Setter触发发送
修改value属性的Setter,在赋值时自动调用send方法,只需给value赋值就能完成发送,语法接近目标需求:
final class CustomPublisher<Output: Any>: Publisher { typealias Failure = Never var value: Output { didSet { wrapper.send(value) } } private var wrapper: CurrentValueSubject<Output, Failure> init(_ value: Output) { self.value = value wrapper = .init(value) } func send(_ value: Output) { self.value = value } func send(subscription: Subscription) { wrapper.send(subscription: subscription) } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { wrapper.receive(subscriber: subscriber) } }
调用方式:
customPublisher.value = newValue
方式二:改为结构体(值类型)实现直接赋值
将CustomPublisher改为结构体,利用值类型的赋值特性,在赋值时触发内部状态更新并发送事件:
struct CustomPublisher<Output: Any>: Publisher { typealias Failure = Never private var wrapper: CurrentValueSubject<Output, Failure> var value: Output { get { wrapper.value } set { wrapper.send(newValue) } } init(_ value: Output) { wrapper = .init(value) } func send(_ value: Output) { wrapper.send(value) } func send(subscription: Subscription) { wrapper.send(subscription: subscription) } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { wrapper.receive(subscriber: subscriber) } // 重载赋值运算符,确保赋值时更新内部状态 static func = (lhs: inout CustomPublisher, rhs: Output) { lhs.value = rhs } }
调用方式:
var customPublisher = CustomPublisher(initialValue) customPublisher = newValue
方式三:实现为属性包装器(最接近@Published的用法)
如果场景和@Published类似,希望给属性添加发布能力,可以将CustomPublisher改为属性包装器:
@propertyWrapper struct CustomPublisher<Output: Any>: Publisher { typealias Failure = Never private var wrapper: CurrentValueSubject<Output, Failure> var wrappedValue: Output { get { wrapper.value } set { wrapper.send(newValue) } } var projectedValue: some Publisher { wrapper } init(wrappedValue value: Output) { wrapper = .init(value) } func send(subscription: Subscription) { wrapper.send(subscription: subscription) } func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { wrapper.receive(subscriber: subscriber) } }
使用方式:
class ViewModel { @CustomPublisher var name: String = "Initial" } let vm = ViewModel() vm.name = "New Value" // 自动触发发送
内容的提问来源于stack exchange,提问作者Petter Braka
相关产品推荐
相关产品推荐

