在 SwiftUI 中使用 UserDefaults 进行全局更新
Global Updates With UserDefaults In SwiftUI
我一直在使用@AppStorage 和UserDefaults 在SwiftUI 中进行更新。如果我对具有 @AppStorage 包装器的 vie 进行更改,则一切正常。我对如何在全球范围内开展这项工作感到困惑。
我使用的结构具有关联的计算属性和格式化程序。这个想法是检查用户默认值并将项目转换为磅或公斤。问题是当 UserDefaults 更新时,使用计算属性的视图不会更新。有没有办法创建一个全局更改来更新下面的 SecondaryView 中的 weightFormatted?
//权重结构
struct Weight {
var weight: Double
var weightFormatted: String {
return weightDecimalLbsOrKgFormatted2(weight)
}
//格式化方法
func weightDecimalLbsOrKgFormatted2(_ lbs: Double) -> String {
if (!UserDefaults.standard.bool(forKey: "weightInKilograms")) {
let weightString = decimalFormatterDecimal2(lbs)
return weightString + "lbs"
} else {
let kg = toKg(lbs)
let weightString = decimalFormatterDecimal2(kg)
return weightString + "kg"
}
}
//设置weightInKilograms的地方
struct AccountView: View {
@AppStorage("weightInKilograms") var weightInKilograms = false
let weight = Weight(weight: 9.0))
var body: some View {
VStack {
Text(weight.weightFormatted)
Toggle(isOn: $weightInKilograms) {
Text("Kilograms")
}
}
}
}
// 次要视图未更新
struct SecondaryView: View {
let weight = Weight(weight: 9.0))
var body: some View {
Text(weight.weightFormatted)
}
}
你的问题是 weight
没有被任何状态包围。
在你的 AccountView
中,给 weight
一个 @State
包装器:
struct AccountView: View {
@AppStorage("weightInKilograms") var weightInKilograms = false
@State var weight = Weight(weight: 9.0))
var body: some View {
//...
}
}
在SecondaryView
中,确保weight
被@Binding
包裹:
struct SecondaryView: View {
@Binding var weight: Weight
var body: some View {
// ...
}
}
然后,在您的第一个视图中将 weight
作为 Binding<Weight>
变量传递给 SecondaryView
:
SecondaryView(weight: $weight)
Is there a way to create a global change that would update weightFormatted in SecondaryView below?
如果您希望进行 全局 更改,您应该考虑设置一个全局 EnvironmentObject
:
class MyGlobalClass: ObservableObject {
// Published variables will update view states when changed.
@Published var weightInKilograms: Bool
{ get {
// Get UserDefaults here
} set {
// Set UserDefaults here
}}
@Published var weight: Weight
}
如果您将 MyGlobalClass
的实例作为 EnvironmentObject
传递给您的主视图,然后再传递给您的辅助视图,则对全局实例中的属性所做的任何更改都将通过以下方式更新视图的状态@Published
包装器:
let global = MyGlobalClass()
/* ... */
// In your app's lifecycle, or where AccountView is instantiated
AccountView().environmentObject(global)
struct AccountView: View {
@EnvironmentObject var global: MyGlobalClass
var body: some View {
// ...
Text(global.weight.weightFormatted)
// ...
SecondaryView().environmentObject(global)
}
}
我一直在使用@AppStorage 和UserDefaults 在SwiftUI 中进行更新。如果我对具有 @AppStorage 包装器的 vie 进行更改,则一切正常。我对如何在全球范围内开展这项工作感到困惑。
我使用的结构具有关联的计算属性和格式化程序。这个想法是检查用户默认值并将项目转换为磅或公斤。问题是当 UserDefaults 更新时,使用计算属性的视图不会更新。有没有办法创建一个全局更改来更新下面的 SecondaryView 中的 weightFormatted?
//权重结构
struct Weight {
var weight: Double
var weightFormatted: String {
return weightDecimalLbsOrKgFormatted2(weight)
}
//格式化方法
func weightDecimalLbsOrKgFormatted2(_ lbs: Double) -> String {
if (!UserDefaults.standard.bool(forKey: "weightInKilograms")) {
let weightString = decimalFormatterDecimal2(lbs)
return weightString + "lbs"
} else {
let kg = toKg(lbs)
let weightString = decimalFormatterDecimal2(kg)
return weightString + "kg"
}
}
//设置weightInKilograms的地方
struct AccountView: View {
@AppStorage("weightInKilograms") var weightInKilograms = false
let weight = Weight(weight: 9.0))
var body: some View {
VStack {
Text(weight.weightFormatted)
Toggle(isOn: $weightInKilograms) {
Text("Kilograms")
}
}
}
}
// 次要视图未更新
struct SecondaryView: View {
let weight = Weight(weight: 9.0))
var body: some View {
Text(weight.weightFormatted)
}
}
你的问题是 weight
没有被任何状态包围。
在你的 AccountView
中,给 weight
一个 @State
包装器:
struct AccountView: View {
@AppStorage("weightInKilograms") var weightInKilograms = false
@State var weight = Weight(weight: 9.0))
var body: some View {
//...
}
}
在SecondaryView
中,确保weight
被@Binding
包裹:
struct SecondaryView: View {
@Binding var weight: Weight
var body: some View {
// ...
}
}
然后,在您的第一个视图中将 weight
作为 Binding<Weight>
变量传递给 SecondaryView
:
SecondaryView(weight: $weight)
Is there a way to create a global change that would update weightFormatted in SecondaryView below?
如果您希望进行 全局 更改,您应该考虑设置一个全局 EnvironmentObject
:
class MyGlobalClass: ObservableObject {
// Published variables will update view states when changed.
@Published var weightInKilograms: Bool
{ get {
// Get UserDefaults here
} set {
// Set UserDefaults here
}}
@Published var weight: Weight
}
如果您将 MyGlobalClass
的实例作为 EnvironmentObject
传递给您的主视图,然后再传递给您的辅助视图,则对全局实例中的属性所做的任何更改都将通过以下方式更新视图的状态@Published
包装器:
let global = MyGlobalClass()
/* ... */
// In your app's lifecycle, or where AccountView is instantiated
AccountView().environmentObject(global)
struct AccountView: View {
@EnvironmentObject var global: MyGlobalClass
var body: some View {
// ...
Text(global.weight.weightFormatted)
// ...
SecondaryView().environmentObject(global)
}
}