【问题标题】:Global Updates With UserDefaults In SwiftUI在 SwiftUI 中使用 UserDefaults 进行全局更新
【发布时间】:2021-06-25 23:33:37
【问题描述】:

我一直在使用 @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)
}
}

【问题讨论】:

    标签: swiftui userdefaults appstorage


    【解决方案1】:

    您的问题是 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)
    

    有没有办法创建一个全局更改来更新下面 SecondaryView 中的 weightFormatted?

    如果您希望进行全局更改,您应该考虑设置一个全局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)
      }
    }
    

    【讨论】:

    • 非常感谢您的回复。我正在添加此信息和一些组合代码以更正此问题。
    猜你喜欢
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 2020-07-01
    • 2021-03-30
    • 2022-01-07
    • 2019-11-11
    • 1970-01-01
    相关资源
    最近更新 更多