Charlie Horton
Charlie Horton

Reputation: 3

Swift array.append() not working as expected

I'm new to Swift and can't seem to get this append method working, any help would be appreciated!

Here are my models and view:

import SwiftUI

struct ContentView: View {
    @Binding var gameInformation: GameInformation
    
    var body: some View {
        VStack(alignment: .center) {
            Button("Append") {
                let index = gameInformation.sets.firstIndex(of: gameInformation.sets.last!)
                gameInformation.sets[index!].legs.append(Leg())
                print(gameInformation.sets[index!].legs)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(gameInformation: .constant(GameInformation()))
    }
}

struct GameInformation: Identifiable, Codable {
    var id = UUID()
    
    var sets: [Set] = [Set()]
    
    enum CodingKeys: String, CodingKey {
         case id, sets
     }
}

struct Set: Codable, Equatable, Identifiable {
    static func == (lhs: Set, rhs: Set) -> Bool {
        return lhs.id == rhs.id
    }
    
    var id: String = UUID().uuidString
    var legs: [Leg] = []
}

struct Leg: Codable, Identifiable {
    var id: String = UUID().uuidString

    var playerOneScores: [Int] = []
    var playerTwoScores: [Int] = []
}

As you can see I have a parent GameInformation model, this has sets which is an array of Set, and then Set has legs which is an array of Leg, the button in the content view simply adds a new Leg but when the value of gameInformation.sets[index!].legs is printed, there's only one entry which is the initialised value.

Thanks again for any help.

Upvotes: 0

Views: 1039

Answers (1)

jnpdx
jnpdx

Reputation: 52575

You've written an implementation of Equatable on Set (which I've renamed to MySet -- see the comments for why) that is getting in your way. Right now, your implementation tells SwiftUI that the elements are equal if the id property is the same. So, if the legs change, SwiftUI doesn't bother updating, because it thinks that the elements are still the same.

Instead, you can remove your custom Equatable conformance and make Leg Equatable as well.

struct GameInformation: Identifiable, Codable {
    var id = UUID()
    
    var sets: [MySet] = [MySet()] //<-- Renamed
    
    enum CodingKeys: String, CodingKey {
         case id, sets
     }
}

struct MySet: Codable, Equatable, Identifiable { //<-- Satisfies Equatable because all of its properties are Equatable
    var id: String = UUID().uuidString
    var legs: [Leg] = []
}

struct Leg: Codable, Identifiable, Equatable { //<-- Marked as Equatable as well
    var id: String = UUID().uuidString

    var playerOneScores: [Int] = []
    var playerTwoScores: [Int] = []
}

Upvotes: 2

Related Questions