1

I have some monthly data that I need to calculate a specific value for before it gets displayed, using:

.onAppear{
     ForEach(monthlyTilt) {item in
          item.degrees = NewValue…        
     }
 }

With a Struct/var combination of:

struct MonthlyTilt: Identifiable {
    var id = UUID().uuidString
    var month: String
    var day: Int
    var degrees: Double
}

var monthlyTilt = [
    MonthlyTilt(month: "Jan",  day: 15,  degrees: 0.0),
    MonthlyTilt(month: "Feb",  day: 46,  degrees: 0.0),
    MonthlyTilt(month: "Mar",  day: 74,  degrees: 0.0),
    MonthlyTilt(month: "Apr",  day: 105, degrees: 0.0),
    MonthlyTilt(month: "May",  day: 135, degrees: 0.0),
    MonthlyTilt(month: "Jun",  day: 166, degrees: 0.0),
    MonthlyTilt(month: "Jul",  day: 196, degrees: 0.0),
    MonthlyTilt(month: "Aug",  day: 227, degrees: 0.0),
    MonthlyTilt(month: "Sept", day: 258, degrees: 0.0),
    MonthlyTilt(month: "Oct",  day: 288, degrees: 0.0),
    MonthlyTilt(month: "Nov",  day: 319, degrees: 0.0),
    MonthlyTilt(month: "Dec",  day: 349, degrees: 0.0)
]

The error message reads: Cannot assign to property: 'item' is a 'let' constant. monthlyTilt is set as a var.

How can I update the degree value?

4
  • 1
    ForEach is used in a View hierarchy. You may be looking for monthlyTilt.forEach Commented Feb 7, 2023 at 17:02
  • Are you trying to update degrees after you already created each struct, or do you just want to format the existing value of degrees differently for display purposes. These are two different approaches. Commented Feb 7, 2023 at 17:26
  • The degrees starts with a zero value and then I want to calculate it with its correct value before the view gets displayed. Commented Feb 7, 2023 at 18:12
  • Calculate it when you change the data, not when its about to be displayed. In SwiftUI it's all about having your data prepared before hand. Commented Feb 7, 2023 at 20:59

1 Answer 1

1

You're trying to update a struct which is, by default, immutable. There are a few different approaches to this. One way is to populate the monthlyTilt var only when you get the data you need to build the structs. You'll probably want to update your datasource to include the month and day as well.

import SwiftUI

public struct FBKChatBotView: View {
    @State private var tilts: [MonthlyTilt] = []
    
    public var body: some View {
      VStack {
        ForEach(tilts) { tilt in
          Text("Tilt is \(tilt.degrees) degrees")
        }
      }
        .onAppear {
           someDataSource() { items in
             items.forEach { item in
               let tilt = MonthlyTilt(month: item.month, day: item.day, degrees: item.degrees)
               tilts.append(tilt)
             }
           }
        }
    }
}

An alternative would be to set up an ObservableObject to handle building that list of an @Published array of tilts and your view would update when that changed. Then you could eliminate the onAppear.

Or, you could create a mutating function in your struct that allows it to set/overwrite its own variables.

struct MonthlyTilt: Identifiable {
    var id = UUID().uuidString
    var month: String
    var day: Int
    var degrees: Double

    mutating func setDegrees(_ to: Double) {
       degrees = to
    }
}

I don't know why, but I never really like that last (mutating) option because it opens the door to other things also mutating the struct and then you lose the strictness of an immutable struct. I don't know if that's best practice or personal preference, but I almost always try not to make structs mutable.

Sample code is off the top of my head so excuse any typos

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.