SwiftUI 文本字段中的可选链接绑定值

Posted

技术标签:

【中文标题】SwiftUI 文本字段中的可选链接绑定值【英文标题】:Optional chaining the binding value in SwiftUI textfield 【发布时间】:2021-11-06 04:31:12 【问题描述】:

我有以下型号:

struct Food: Codable, Identifiable 
    var id = UUID()
    var name: String = ""
    var energy: Float?
    var water: Float?
    var macroProfile: MacronutrientProfile?


struct MacronutrientProfile: Codable 
    var carb: Float?
    var protein: Float?
    var fat: Float?

我正在尝试将此模型实例的值绑定到 TextField,如下所示:

struct FoodEditView: View 
    @State var food: Food
    var body: some View 
        Form 
            Section(header: Text("Basics").fontWeight(.bold)) 
                HStack 
                    Text("Name")
                    Spacer()
                    TextField("Name", text: $food.name)
                    .multilineTextAlignment(.trailing)
                
                HStack 
                    Text("Energy")
                    Spacer()
                    TextField("Calories", value: $food.energy, formatter: calorie)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.numberPad)
                
                HStack 
                    Text("Water")
                    Spacer()
                    TextField("Grams", value: $food.water, formatter: gram)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.numberPad)
                
            
            .textCase(.none)
            Section(header: Text("Macronutrients").fontWeight(.bold)) 
                HStack 
                    Text("Carbohydrates")
                    Spacer()
                    TextField("Grams", value: $food.macroProfile?.carb, formatter: gram)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.numberPad)
                
                HStack 
                    Text("Protein")
                    Spacer()
                    TextField("Grams", value: $food.macroProfile?.protein, formatter: gram)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.numberPad)
                
                HStack 
                    Text("Fat")
                    Spacer()
                    TextField("Grams", value: $food.macroProfile?.fat, formatter: gram)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.numberPad)
                
            
            .textCase(.none)

在链接macroProfile 时,我是这个相当奇怪的一长串错误:

我的问题是,当可选链接macroProfile 而不是使用energywater(这两个也是可选值)时,我怎么会得到这些错误?解决此问题的最佳方法是什么?

【问题讨论】:

使用自定义绑定:***.com/a/59642601/14733292 【参考方案1】:

Binding 上使用“点链接”语法时,它是创建Binding 的快捷语法。它与点语法通常具有的“查找此事物的属性”的语义不同。

所以$food.name不会解决food 的绑定然后引用它的属性之一。它将为食物的name 属性创建双向Binding<String>

同样,当您拥有$food.macroProfile 时,该表达式的值是Binding<MacroNutrientProfile?>... 一个将直接更改food 中的值的绑定(并且它可以更改的值是可选的)。它不是对绑定 $food 的解析,然后引用该对象的属性之一。

$food.macroProfile?.carb 是无意义的,因为$food.macroProfile 属于Binding<MacroNutrientProfile?> 类型,它不是可选类型。所以你会看到错误。

$food.name 不是无意义的,因为它是 Binding<String>,并且您不会尝试将非可选值视为可选值。

改变它的一种方法是使用自定义绑定:

struct Food: Codable, Identifiable 
    var id = UUID()
    var name: String = ""
    var energy: Float?
    var water: Float?
    var macroProfile: MacronutrientProfile?


struct MacronutrientProfile: Codable 
    var carb: Float?
    var protein: Float?
    var fat: Float?


struct SomeView : View 
    @State var food: Food
    let gram = NumberFormatter()

    var body : some View 
        let carbBinding = Binding<Float?>(get:  food.macroProfile?.carb ,
                                          set:  newValue in food.macroProfile?.carb = newValue )

        return HStack 
           Text("Carbohydrates")
           Spacer()
            TextField("Grams", value: carbBinding, formatter: gram)
           .multilineTextAlignment(.trailing)
           .keyboardType(.numberPad)
       
    

【讨论】:

谢谢!信息量很大。这回答了我问题的第一部分。现在,我该如何解决? 我添加了一个代码示例来演示一种方式。 真的没有更好的办法吗?这感觉有点麻烦。如果我的食物模型变得更大,我必须为每个嵌套对象创建一个自定义绑定。

以上是关于SwiftUI 文本字段中的可选链接绑定值的主要内容,如果未能解决你的问题,请参考以下文章

参数 SwiftUI 中的可选绑定

SwiftUI 中的可选绑定

SwiftUI 中的可选状态或绑定

ES11中的可选链等语法

ES11中的可选链等语法

javascript中的可选链操作符