0

I have an array that I want to change based on another variable, so that different things are displayed based on that variable's value.

In the below example, the variable that changes is "scores", and I want to display a different message list depending on what that value of "scores" is.

In the below example, I call a function and pass it "scores", it correctly returns a structure "Messages". All that works fine.

The problem occurs when "Messages" has an array size that is less than the previous value of Messages. i.e., if scores = 1, then the code runs fine, but if scores = 2, then "Messages.message[section]" crashes because the index is out of range. It therefore seems that the way my code works is that it just overwrites part of the "Messages" array, rather than recreates it. How do I solve that?

Many thanks!

Example code (simplified slightly for display purposes):

class MessageGetter: ObservableObject {
@Published var message = [
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”]),
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”]),
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”])
   ]
   
func changemessage(scores: Int) {
    
    if scores == 1 {
        
        self.message = [
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”]),
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”]),
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”])
   ]

    }
    else if scores == 2 {
        
        self.message = [
          
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”]),
    MessageStructure(messageType: 2, textsFrom: [“text1”, “text2”])
   ]
    }

}
}

struct MessageStructure: Identifiable {
    var id = UUID()
    var messageType: Int 
    var textsFrom: [String] 
  
}


struct MessagesView: View {
@State var showNavigation1: Bool = false
@StateObject var settings = GameSettings()

var Messages = MessageGetter()


var body: some View {
    NavigationView {
    
        
        List {
            ForEach(0..<Messages.message.count) { section in

    NavigationLink(destination: MessageDetailView(message: Messages.message[section])) {

                    MessagesRow(message: Messages.message[section])
                       
            }
            }
        }.navigationTitle("Messages")
            .listStyle(PlainListStyle())
        
        
    }
    .environmentObject(settings)
    .onAppear(perform: {Messages.changemessage(scores: settings.score)}) 

    
}
}


     
  • Will it also crash if you loop over the objects rather than using a counter, `ForEach(Messages.message) { message in…. }` (or similar)? – Joakim Danielson Jan 31 '22 at 22:07
  • Does this answer your question https://stackoverflow.com/a/59007863/12299030? – Asperi Feb 01 '22 at 06:11
  • I couldn't seem to make either solution wok :( – Carl Bryers Feb 01 '22 at 22:06
  • @Asperi - I think the problem is that the range in the foreach loop remains the same rather than dynamically updating each time. That solution you posted doesn't seem to work here, but that's the reason why it crashes. I have a rough fix where I set the for loop to run from 0 to 10 (where 10 is always greater than Messages.message.count), and add the NavigationLink part into an if section <= Messages.message.count -1 {} condition. Its rough, but it works for now. – Carl Bryers Feb 02 '22 at 21:36

1 Answers1

0

if you want the view to be updated with the messages it has to be a @State var or a Binding, or be @Observed... for the view - simple var is got once and it just doesn't see if the number is changing

Roman R
  • 39
  • 8