SwiftUI-全局更改时更新@State

时间:2019-10-27 22:02:11

标签: swiftui

当另一个视图上的数据更改时,我想更新概述视图上的UI元素。

我研究了@EnvironmentalObject和@Binding。但是,对这两个对象的更新似乎都不会强制重新加载视图。仅更改@State force renders。
另外,在以下情况下,ChangeView也不是OverviewView的子级。因此,@ Binding仍然不是一个选择。

Data.swift

struct ExampleData : Hashable {
 var id: UUID
 var name: String
}

var globalVar: ExampleData = ExampleData(id: UUID(), name:"")

OverviewView.swift

struct OverviewView: View {
    @State private var data: ExampleData = globalVar
    var body: some View {
       Text(data.name)
    }
}

ChangeView.swift

struct ChangeView: View {
    @State private var data: ExampleData = globalVar
    var body: some View {
       TextField("Name", text: $data.name, onEditingChanged: { _ in 
          globalVar = data }, onCommit: { globalVar = data })
    }
}

ChangeView TextField中的更改将更新globalVar。但是,切换回视图时,这不会更新OverviewView上的Text。

我知道使用全局变量是“丑陋”的编码。如何处理将在众多无关视图中使用的数据?

请提供有关如何更好地处理这种情况的建议。

1 个答案:

答案 0 :(得分:2)

OverviewViewChangeView在其data变量中拥有ExampleData结构的不同副本(将结构分配给另一个变量时,实际上是在复制它,而不是像对象。)因此更改其中一个不会影响另一个。

@EnvironmentObject适合您的要求。

这是一个例子:
由于我们正在使用@EnvironmentObject,因此您需要将ExampleData转换为 一个类,或使用一个类来存储它。我将使用后者。

class ExampleDataHolder: ObservableObject {
    @Published var data: ExampleData = ExampleData(id: UUID(), name:"")
}

struct CommonAncestorOfTheViews: View {
    var body: some View {
       CommonAncestorView()
          .environmentObject(ExampleDataHolder())
    }
}

struct OverviewView: View {
    @EnvironmentObject var dataHolder: ExampleDataHolder

    var body: some View {
       Text(dataHolder.data.name)
    }
}

struct ChangeView: View {
    @EnvironmentObject var dataHolder: ExampleDataHolder

    var body: some View {
       TextField("Name", text: $dataHolder.data.name)
    }
}