swiftclassequalityswiftdata

Class I made not showing up as equal when equal


I have a custom class for holding a collection of quotes in swiftData in my app. It looks like this:

@Model
final class CollectionData: Equatable {
    var name: String
    var data: [Quote]
    var id: UUID = UUID()
    
    init(data: [Quote], name: String) {
        self.data = data
        self.name = name
    }
}

But when I compare equal empty versions it outputs false.

.onAppear {
var test = CollectionData(data: [], name: "") == CollectionData(data: [], name: "")
print(test) //prints false
}

I can't figure out what is causing this strange behavior, any help will be appreciated.


Solution

  • If you really want to compare two CollectionData without interfering with the SwiftData system, try this approach using simple functions that exclude the id, as shown in this SwiftUI example code:

    // for testing
    @Model
    final class Quote {
        var text: String
    
        init(text: String) {
            self.text = text
        }
        
        func isEqual(to other: Quote) -> Bool {
            return text == other.text
        }
    }
    
    @Model
    final class CollectionData {
        var name: String
        var data: [Quote]
        
        init(data: [Quote], name: String) {
            self.data = data
            self.name = name
        }
        
        func isEqual(to other: CollectionData) -> Bool {
            return isEqualQuotes(data, other.data) && name == other.name
        }
        
        func isEqualQuotes(_ lhs: [Quote], _ rhs: [Quote]) -> Bool {
            guard lhs.count == rhs.count else { return false }
            let sortedLhs = lhs.sorted { $0.text < $1.text }
            let sortedRhs = rhs.sorted { $0.text < $1.text }
            return zip(sortedLhs, sortedRhs).allSatisfy { $0.isEqual(to: $1) }
        }
    }
    
    struct ContentView: View {
        // ....
        @State private var result = false
        
        var body: some View {
            Text(result ? "collections are equal" : "collections NOT equal").font(.title)
                .onAppear {
                    let collectionData1 = CollectionData(data: [Quote(text: "quote1"),Quote(text: "quote2")], name: "test1")
                    let collectionData2 = CollectionData(data: [Quote(text: "quote2"),Quote(text: "quote1")], name: "test1")
                    result = collectionData1.isEqual(to: collectionData2)
                    if result {
                        print("---> collections are equal")
                    } else {
                        print("---> collections NOT equal")
                    }
                }
        }
    }