SwiftUI-通过嵌套引用类型传播更改通知 [英] SwiftUI - propagating change notifications through nested reference types
问题描述
我想将SwiftUI中的ObservableObject行为扩展到嵌套类,并且我正在寻找正确的方法来做到这一点.可以使用Combine来手动"完成,但是我想有一种使用SwiftUI的更简洁的方法,我希望您能为我指明正确的方向.这就是我的意思……
I'd like to extend ObservableObject behavior in SwiftUI to nested classes, and I'm looking for the proper way to do it. It can be done "manually" with Combine, but I imagine there's a much cleaner way to do it using SwiftUI, and I'm hoping you can point me in the right direction. Here's what I mean…
以下是ObservableObject的典型应用程序,用于使View动态响应对引用类型的更改.轻击按钮可切换showText
值,使文本在屏幕上显示/消失:
Below is a typical application of ObservableObject to make a View dynamically respond to changes to a reference type. Tapping the button toggles the showText
value, which makes the text appear/disappear on the screen:
import SwiftUI
class MyClass: ObservableObject {
@Published var showText = false
}
struct ContentView: View {
@ObservedObject var instance = MyClass()
var body: some View {
VStack(spacing: 10) {
Button(action: {
print(self.instance.showText)
self.instance.showText.toggle()
}) {
Text("BUTTON").bold().padding()
.foregroundColor(.white)
.background(Color.red)
}
if instance.showText {
Text("Hello, World!")
}
}
}
}
这很好.
但是下面的修改呢?其中包含showText
的类是InnerClass
,其自身包含在OuterClass
中呢?该按钮可以很好地切换showText
,但是值更改的通知不再通过OuterClass
实例传播到视图,因此视图不再显示文本.
But what about the modification below, where the class containing showText
is an InnerClass
, itself contained in an OuterClass
? The button toggles showText
just fine, but the notification of the value change no longer propagates through the OuterClass
instance to the View, so the View no longer displays the Text at all.
import SwiftUI
class OuterClass: ObservableObject {
@Published var innerInstance = InnerClass()
}
class InnerClass: ObservableObject {
@Published var showText = false
}
struct ContentView: View {
@ObservedObject var outerInstance = OuterClass()
var body: some View {
VStack(spacing: 10) {
Button(action: {
self.outerInstance.innerInstance.showText.toggle()
}) {
Text("BUTTON").bold().padding()
.foregroundColor(.white)
.background(Color.red)
}
if outerInstance.innerInstance.showText {
Text("Hello, World!")
}
}
}
}
什么是优雅的解决方案?
What is the elegant fix for this?
推荐答案
可以在您的模型中完成
import Combine // required for AnyCancelable
class OuterClass: ObservableObject {
private let _inner: InnerClass
var innerInstance: InnerClass {
return _inner
}
var store = Set<AnyCancellable>()
init(_ inner: InnerClass) {
_inner = inner
inner.$showText.sink { [weak self] _ in
self?.objectWillChange.send()
}.store(in: &store)
}
}
以及示例中的用法
import SwiftUI
import Combine
class OuterClass: ObservableObject {
private let _inner: InnerClass
var innerInstance: InnerClass {
return _inner
}
var store = Set<AnyCancellable>()
init(_ inner: InnerClass) {
_inner = inner
inner.$showText.sink { [weak self] _ in
self?.objectWillChange.send()
}.store(in: &store)
}
}
class InnerClass: ObservableObject {
@Published var showText = false
}
let inner = InnerClass()
let outer = OuterClass(inner)
struct ContentView: View {
@ObservedObject var outerInstance = outer
var body: some View {
VStack(spacing: 10) {
Button(action: {
self.outerInstance.innerInstance.showText.toggle()
}) {
Text("BUTTON").bold().padding()
.foregroundColor(.white)
.background(Color.red)
}
if outerInstance.innerInstance.showText {
Text("Hello, World!")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
如果您希望观察内部物体的任何变化,那就去做吧!
if you like to observe any change in your inner object, just do it!
class OuterClass: ObservableObject {
private let _inner: InnerClass
var innerInstance: InnerClass {
return _inner
}
var store = Set<AnyCancellable>()
init(_ inner: InnerClass) {
_inner = inner
inner.objectWillChange.sink { [weak self] _ in
self?.objectWillChange.send()
}.store(in: &store)
}
}
更新:基于以下讨论
class OuterClass: Combine.ObservableObject {
private let _inner: InnerClass
var innerInstance: InnerClass {
return _inner
}
var store = Set<AnyCancellable>()
init(_ inner: InnerClass) {
_inner = inner
inner.objectWillChange.sink { [weak self] _ in
self?.objectWillChange.send()
}.store(in: &store)
}
}
这篇关于SwiftUI-通过嵌套引用类型传播更改通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!