如何在引用ObservableObject类中的Published,但在两个类之间的视图中创建类似于绑定的机制?也就是说,从类A调用类B构造函数,传递来自类A的prop1。在类B中存在prop2,这些prop1和prop2应该相互镜像。
附言:附加的代码不起作用,只是直观地显示我想要什么。。。
PPS:类A中的prop1和类B中的prop2,必须按条件发布。它自己的观点也被订阅了
PPPS:重要的是在ClassB中有任何绑定逻辑,以便于重用。
class ClassA: ObservableObject {
@Published var prop1: Bool = false //When prop1 changed, it must be reflected in prop2
let classB: ClassB
init() {
classB = .init(prop2: _prop1) //Should stay that simple, no setup here, passing only property, ClassB doesn't know about ClassA.
}
}
class ClassB: ObservableObject {
@Published var prop2: Bool //When prop2 changed, it must be reflected in prop1
init(prop2: Published<Bool>) {
_prop2 = prop2
}
}
一个简单但通用的解决方案可能如下所示。
添加以下扩展:
extension Published.Publisher where Value: Equatable {
mutating func link(with other: inout Self) {
removeDuplicates().assign(to: &other)
other.removeDuplicates().assign(to: &self)
}
}
这只适用于符合Equatable
的值,因为否则您可能会陷入无休止的循环。
然后调用ClassA
:初始化器中的扩展
classB.$prop2.link(with: &$prop1)
原始答案
一个简单的解决方案是将以下代码放入ClassA
的init
中:
$prop1
.removeDuplicates()
.assign(to: &classB.$prop2) // mirror changes of prop1 into classB.prop2
classB.$prop2
.removeDuplicates()
.assign(to: &$prop1) // mirror changes of classB.prop2 into prop1
但是,我建议从ClassA
中删除prop1
,并分别通过classB.prop2
和classB.$prop2
访问此值。这使得依赖关系更加清晰,并且不需要在两个位置存储和更新值。
注释中关于将逻辑放入ClassB的问题的答案
为此,您可以在ClassB
中添加一个执行链接的函数:
fileprivate func linkProps(to classA: ClassA) {
$prop2
.removeDuplicates()
.assign(to: &classA.$prop1) // mirror changes of prop2 into classA.prop1
classA.$prop1
.removeDuplicates()
.assign(to: &$prop2) // mirror changes of classA.prop1 into prop2
}
然后在ClassA
的init
中调用此函数(以及其他需要调用的地方(:
init() {
classB = .init(prop2: _prop1)
classB.linkProps(to: self)
}
评论中关于阻止ClassB了解ClassA的问题的答案
这可以通过只将属性包装器的投影值传递到ClassB
:上的函数中来实现
fileprivate func linkProp2(to prop1: inout Published<Bool>.Publisher) {
$prop2
.removeDuplicates()
.assign(to: &prop1) // mirror changes of prop2 into prop1
prop1
.removeDuplicates()
.assign(to: &$prop2) // mirror changes of prop1 into prop2
}
ClassA
初始值设定项中的调用将如下所示:
classB.linkProp2(to: &$prop1)