@State var 不更新 SwiftUI 视图

@State var not updating SwiftUI View

我想让我的内容视图显示对应用程序来说是全局的并且在内容视图本身之外进行操作的数据。

swift 是否有允许外部变量的绑定?

我已经创建了我认为最基本的应用程序:

//
//  myTestxApp.swift
//  myTestx

import SwiftUI

var myStng = "Hello\n"
var myArray = ["Hello\n"]

func myTest(){
    myStng.append("Hello\n")
    myArray.append("Hello\n")
    print(myStng,myArray)
}

@main
struct myTestxApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

//
//  ContentView.swift
//  myTestx
import SwiftUI
struct ContentView: View {
    @State var i = myStng
    @State var j = myArray
    
    var body: some View {
        VStack{
        Button( action: myTest ){ Text("Update") }
        List{ Text(i).padding() }
        List{ ForEach(myArray, id: \.self)
            {  i in Text(i).padding()} }
        } //end VStack
    } //end View
} //end ContentView

我声明了两个应用程序全局变量,有一个更新它们的外部函数,对于这个例子,一个带有函数调用按钮的视图和列表区域,用于通过 @State 变量绑定的更新结果。在我计划的应用程序中,更新功能将成为数据处理的一部分 activity。我希望能够编辑数据并让内容视图在更新该数据项时更新显示的数据。在这个例子中:

代码编译运行,控制台显示两个变量正在更新,但是视图控制器没有响应状态变化? @State 是适合使用的绑定还是我应该使用其他方法使内容视图项识别内容更改?

任何指点将不胜感激。

正如其他人所建议的那样,使用全局变量时必须非常小心,你应该只将它们暴露在需要的范围内。

问题是您在治疗 @State var i = myStng 时认为这会在 imyStng 之间建立反应性联系,但 事实并非如此.此行在 i 和 SwiftUI 为您管理的内存地址之间创建了一个反应式连接,其第一个值是 myStng 在那个确切时刻的值。

无论如何,我正在发布一个示例,说明如何使用环境对象和您提供的代码来实现您的目标。

import SwiftUI

class GlobalVariables: ObservableObject{
    @Published var myStng = "Hello\n"
    @Published var myArray = ["Hello\n"]
}

func myTest(variables: GlobalVariables){
    variables.myStng.append("Hello\n")
    variables.myArray.append("Hello\n")
}

@main
struct myTestxApp: App {
    @StateObject var globalEnvironment = GlobalVariables()
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(globalEnvironment)
        }
    }
}

//
//  ContentView.swift
//  myTestx
//import SwiftUI
struct ContentView: View {
    @EnvironmentObject var global: GlobalVariables
    
    var body: some View {
        VStack{
            Button {
                myTest(variables: global)
            } label: {
                Text("Update")
            }

            List{ Text(global.myStng).padding() }
            List{ ForEach(global.myArray, id: \.self)
            {  i in Text(i).padding()} }
        } //end VStack
    } //end View
} //end ContentView