在 SwiftUI 中的 Observable 对象中存储绑定

问题描述 投票:0回答:1

我正在创建一个 Mac 应用程序。当多次启动时,所有窗口都应访问相同应用程序状态(

theAppState
),但每个窗口应显示自己的数据(类型为
MyClass
)。

如下所示,当

MainWindow
创建
MyClass
对象时,它将绑定传递给
theAppState

MainWindow
有一个调用
obj.incBoth()
的按钮。结果,
theAppState
增加(理应如此)。

身体以不同的方式显示

theAppState

  1. self.appState
    正确 显示,并且每次按下按钮都会增加。
  2. obj.appstate
    正确显示(始终显示原始值42
  3. obj.appstate()
    正确显示(与 obj.appstate 相同)

请帮助我理解这种奇怪的行为!

更新: 请注意,视图和

MyClass
对象 (obj) 都可以通过其本地绑定访问
theAppState
。在视图中,
self.appState
返回 Correct 值,并且对象在 incBoth() 中打印出
 Correct
值。我觉得奇怪的是,视图无法通过 obj.appstate2() 间接访问 AppState 。您的评论表明不应在
StateObject
中使用绑定。这可能是正确的,但它确实解释了奇怪的行为。
import SwiftUI

class MyClass : ObservableObject {
    @Published var x = 0
    @Binding var appstate : Int
    
    init(appstate : Binding<Int> ){
        self._appstate = appstate
    }
    
    func appstate2() -> Int {
        return self.appstate
    }
    func incBoth() {
        x+=1
        appstate += 1
        print("x=\(x) appstate=\(appstate)")
    }
}

struct MainView : View {
    @Binding var appState : Int
    @StateObject var obj : MyClass
    
    init(appstate: Binding<Int>){
        self._appState = appstate
        self._obj = StateObject(wrappedValue: MyClass(appstate: appstate))
    }
    
    var body: some View {
        Text("appState = \(appState),  obj.appstate = \(obj.appstate), obj.appstate2 = \(obj.appstate2())   obj.x = \(obj.x)")
        Button("Inc") {
            obj.incBoth()
        }
    }
}

@main
struct ProblemApp : App {
    @State private var theAppState = 42
    
    var body: some Scene {
        WindowGroup {
            MainView(appstate: $theAppState)
        }
    }
}


ios swift macos swiftui data-binding
1个回答
1
投票
@State

可以只是一个结构,然后你可以将逻辑放入函数中,例如

struct TheAppState {
    var x = 42

    mutating func inc() {
        x += 1
    }
}
struct ProblemApp : App {
    @State private var theAppState = TheAppState()

在 SwiftUI 中,状态被设计为去中心化的,因此您需要小心,仅将相关变量放在结构中,而不是全局变量中。否则 
body

将不会像平常那样有效地被调用。

在 SwiftUI 中,通常尽量避免自定义类,因为这会导致一致性问题,而 Swift 使用结构的目的就是为了消除这种问题。

© www.soinside.com 2019 - 2024. All rights reserved.