【问题标题】:Swift chains of @ObservableObject@ObservableObject 的 Swift 链
【发布时间】:2021-11-03 22:30:55
【问题描述】:

在我的 Swift 项目中,数据和触发数据变化的前端按钮被多层对象隔开。如何使前端视图反映删除了几层的更改?我想这是 Swift 开发中相当普遍的情况。

这是一个工作示例,视图和数据之间没有分隔层。

import Foundation
import SwiftUI
import OrderedCollections

class Test: ObservableObject {
    @Published var array: [String] = []
    var num: Int = 0
    
    func add() {
        array.append(String(num))
        num += 1
    }
}


struct testView: View {
    @ObservedObject var test = Test()
    var body: some View {
        VStack {
            Button(action: { test.add() }) {
                Text("Add Item to Array")
            }
            Text("")
            Text("Items")
            Text(Array(test.array).description)
        }
    }
}

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            testView()
        }
    }
}

这是一个“中间”类不起作用的示例。

class Test: ObservableObject {
    @Published var array: [String] = []
    var num: Int = 0
    
    func add() {
        array.append(String(num))
        num += 1
    }
}

class Middle: ObservableObject {
    @ObservedObject var test: Test = Test()
}


struct testView: View {
    @ObservedObject var m = Middle()
    var body: some View {
        VStack {
            Button(action: { m.test.add() }) {
                Text("Add Item to Array")
            }
            Text("")
            Text("Items")
            Text(Array(m.test.array).description)
        }
    }
}

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            testView()
        }
    }
}

注意:使用其他代码,我似乎已经能够让我的视图更新远离前端的变化数据。我确信这是可能的——我正在寻找的是使这项工作的系统方法(我当前的方法只是将@ObservableObject、@Published 和@ObservedObject 添加到数据接触的所有内容中,直到它工作——或不工作' t)。

【问题讨论】:

    标签: swift class observable


    【解决方案1】:

    可能有一些元素很好理解。最重要的是:

    1. @ObservedObject 属性包装器用于在 View 中使用——如果在另一个 ObservableObject 中使用 则它不会做任何事情

    2. @Published 只能在使用值类型时开箱即用。在 Swift 中,这意味着使用 structs 而不是 classes。

    关于第二点,除非有真正令人信服的理由不这样做,否则您的模型应该是structs。这意味着您可以只使用 @Published 属性来存储它们,一切都会正常工作:

    struct Test {
        var array: [String] = []
        var num: Int = 0
    }
    
    class Middle: ObservableObject {
      @Published var test: Test = Test()
    
      func append() {
        test.array.append(String(test.num))
        test.num += 1
      }
    }
    

    如果出于某种原因不得不使用嵌套对象,则必须手动调用 objectWillChange.send() 来告诉 SwiftUI View @Published 属性有新数据:

    class Test : ObservableObject {
        var array: [String] = []
        var num: Int = 0
        
        func append() {
          array.append(String(num))
          num += 1
        }
    }
    
    class Middle: ObservableObject {
      @Published var test: Test = Test()
    
        func append() {
            test.append()
            self.objectWillChange.send()
        }
    }
    

    您还可以搜索“SwiftUI 嵌套的 ObservableObject”,这将为您提供有关此主题的大量现有对话,包括:

    How to tell SwiftUI views to bind to nested ObservableObjects

    【讨论】:

    • 如何在一个struct方法中修改多个实例变量?我正在尝试将我的类繁重的逻辑代码转换为结构。我的 struct 方法正在发生变异并具有 inout 参数,但出现“对自身的重叠访问”错误
    • 你能举个例子吗?我想可能是在一个新问题中。
    • 一个不相关的问题...如何在没有类控制器的情况下直接将结构发布到视图?
    • 我不确定这意味着什么。您的意思是如何使用结构作为视图的参数?就像任何其他参数一样。
    • 如何将一个结构传递给一个视图,同时也让视图随着结构的变化而更新(或者更确切地说是创建一个新的结构)?结构体不能符合 ObservableObject 协议?
    猜你喜欢
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 2021-07-06
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2021-02-27
    • 1970-01-01
    相关资源
    最近更新 更多