绑定 didSet 变量以更新计算的 var

问题描述 投票:0回答:1

我正在创建一个营养追踪器,当食物的数量发生变化时,我需要更新营养素。这取决于食物中的营养和食用量(很明显)。我试图在数量变化时更新我的计算变量(营养素),但到目前为止我只是将对象的数量重新初始化为 1,而不是绑定文本字段中设置的值。

还有一个测量选择器需要更新和设置营养值,但为了简单起见,我只包含了数量字段。谁能告诉我我的想法哪里错了?

示例结构

struct Intake: Identifiable, Equatable, Hashable {
    var id : String = UUID().uuidString
    var amount: Double = 1 {
        didSet {
            updateNutrients()
    }

    var nutrients: Nutrients = Nutrients()

    init(food: Food) {
        self.food = food
        print("reinitalizing food")
        updateNutrients()
    }

    private mutating func updateNutrients() {
        nutrients = Nutrients(
            carb: self.food.consumableProps.nutrients.carb ?? 0 * self.amount, 
            fat: self.food.consumableProps.nutrients.fat ?? 0 * self.amount,
            protein: self.food.consumableProps.nutrients.protein ?? 0 * self.amount,
            transFat: self.food.consumableProps.nutrients.transFat ?? 0 * self.amount,
            saturatedFat: self.food.consumableProps.nutrients.saturatedFat ?? 0 * self.amount,
            sodium: self.food.consumableProps.nutrients.sodium ?? 0 * self.amount,
            fiber: self.food.consumableProps.nutrients.fiber ?? 0 * self.amount,
            sugars: self.food.consumableProps.nutrients.sugars ?? 0 * self.amount,
            cholesterol: self.food.consumableProps.nutrients.cholesterol ?? 0 * self.amount,
            calcium: self.food.consumableProps.nutrients.calcium ?? 0 * self.amount,
            iron: self.food.consumableProps.nutrients.iron ?? 0 * self.amount,
            potassium: self.food.consumableProps.nutrients.potassium ?? 0 * self.amount,
            magnesium: self.food.consumableProps.nutrients.magnesium ?? 0 * self.amount,
            calories: self.food.consumableProps.nutrients.calories ?? 0 * self.amount
        )
    }

视图中的示例绑定:

struct IntakeRow:View{
   @Binding var intake:Intake

   var body: some View{
      VStack{
         TextField("Amount", value: $amount, formatter: NumberFormatter())
         HStack(spacing: 10) {
                nutrientText(macro: .carb, nutrients.carb ?? 0, format: "%.0f")
                    .frame(width: g.size.width/5)
                nutrientText(macro: .fat, nutrients.fat ?? 0, format: "%.0f")
                    .frame(width: g.size.width/5)
                nutrientText(macro: .protein, nutrients.protein ?? 0, format: "%.0f")
                    .frame(width: g.size.width/5)
            }.frame(height:g.size.height)
        }
    }
    
    private func nutrientText(macro: Macro, _ value: Double, format: String) -> some View {
        return Text(String(format: format, value))
            .font(.system(size: 14, weight: .semibold))
            .foregroundColor(macro.color)
            .minimumScaleFactor(0.8)
            .lineLimit(1)
    }

swift swiftui binding
1个回答
0
投票

我无法对此进行测试,因为您的代码无法编译(如果问题已更新,将更新我的答案)但这应该可以解决您的部分问题:

    self.food.consumableProps.nutrients.magnesium * self.amount ?? 0 
    
    // instead of 
   
    self.food.consumableProps.nutrients.magnesium ?? 0 * self.amount

   // Repeat for all of the `Nutrients` init parameters

现在所有

updateNutrients
所做的就是匹配存储在
self.food.consumableProps.nutrients
中的值,或者如果这些值中的任何一个是
nil
,则传入0。

关于

amount
值被设置回1,我可以想象两个原因:

  1. 它从未真正改变过(看起来你将
    TextField
    绑定到
    $amount
    而不是
    $intake.amount
    ,尽管这可能是复制代码时的错误。)
  2. 你以某种方式重新初始化结构/创建一个新值而不是更新
    var
    .
© www.soinside.com 2019 - 2024. All rights reserved.