SwiftUI-通过嵌套引用类型传播更改通知 [英] SwiftUI - propagating change notifications through nested reference types

查看:142
本文介绍了SwiftUI-通过嵌套引用类型传播更改通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆