如何使用 Combine 绑定两个 类 之间的属性?
How to bind properties between two classes with Combine?
如何在引用ObservableObjectclass中的Published的view中做一个类似于binding的机制,但是介于2classes之间?即从classA,调用classB的构造函数,从classA传入prop1。而在classB中prop2存在,这些prop1和prop2应该镜像彼此。
PS: 附上的代码不起作用,只是直观地展示我想要的...
PPS: ClassA 中的 prop1 和 ClassB 中的 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)
如何在引用ObservableObjectclass中的Published的view中做一个类似于binding的机制,但是介于2classes之间?即从classA,调用classB的构造函数,从classA传入prop1。而在classB中prop2存在,这些prop1和prop2应该镜像彼此。
PS: 附上的代码不起作用,只是直观地展示我想要的...
PPS: ClassA 中的 prop1 和 ClassB 中的 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)