PaytonDEV
PaytonDEV

Reputation: 131

Type 'CounterModel' does not conform to protocol 'PersistentModel` - SwiftData

I am trying to make a sample app which uses SwiftData to keep track of sports goals. I have a struct: Team which has values id (UUID), name (string), score (int), and editing (bool). I have a SwiftData model class which contains the values id (UUID), teams ([Team]), pro (Boolean). Normally, the class works fine without having the teams array in the CounterModel class, but as soon as I add var teams: [Team] to the class, I get the following errors:


The class conforms to Identifiable, Hashable. The struct also conforms to these protocols. Conforming both to Codable does not make the error go away. Here is my code if needed:
import Foundation
import SwiftData

@Model
class CounterModel: Identifiable, Hashable {
    @Attribute(.unique) var id = UUID()
    var teams: [Team]
    var pro: Bool
    
    init(teams: [Team], pro: Bool) {
        self.teams = teams
        self.pro = pro
    }
    func toTeamArr() -> [Team] {
        return teams
    }
    
}
struct Team: Identifiable, Hashable {
    var id: UUID = UUID()
    var name: String
    var score: Int
    var editing: Bool = false
}

I have also tried putting the Team struct inside of the class. Same error.

Following a suggestion by a reply, Here is the updated code:

import Foundation
import SwiftData

@Model
class CounterModel: Identifiable, Hashable {
    @Attribute(.unique) var id = UUID()
    @Relationship(.cascade) var teams: [Team]
    var pro: Bool
    
    init(teams: [Team], pro: Bool) {
        self.teams = teams
        self.pro = pro
    }
    func toTeamArr() -> [Team] {
        return teams
    }
}

@Model
class Team: Identifiable, Hashable {
    @Attribute(.unique) var id: UUID = UUID()
    var name: String
    var score: Int
    @Transient var editing: Bool = false
    
    init(name: String, score: Int, editing: Bool = false) {
        self.name = name
        self.score = score
        self.editing = editing
    }
}

Now, there are only 2 errors produced:

Upon extracting the models into a separate Xcode project, it builds fine. When I bring the rest of my code into the project, it stops working. Will investigate further.

Okay. It seems to be an issue with passing the data from the @Query modifier into different views. Upon removing the parameters for the CounterModel data model from the views, the app compiled fine. I'm assuming, and hoping that this is a bug. For now, I'll just query the data separately in the views. Thank you all for your help! I have submitted feedback on the issue, just in case: FB12338703

Upvotes: 2

Views: 1359

Answers (2)

PaytonDEV
PaytonDEV

Reputation: 131

Okay. It seems to be an issue with passing the data from the @Query modifier into different views. Upon removing the parameters for the CounterModel data model from the views, the app compiled fine. I'm assuming, and hoping that this is a bug. For now, I'll just query the data separately in the views. Thank you all for your help!

Upvotes: 3

Paulw11
Paulw11

Reputation: 114773

There are two changes you need to make to your model classes.

The first, is to change Team to a class and make it an @Model The second change is to tell SwiftData that teams is a reference to another SwiftData entity using the @Relationship decorator.

class CounterModel: Identifiable, Hashable {
    @Attribute(.unique) var id = UUID()
    @Relationship(.cascade) var teams: [Team]
    var pro: Bool
    
    init(teams: [Team], pro: Bool) {
        self.teams = teams
        self.pro = pro
    }
    func toTeamArr() -> [Team] {
        return teams
    }
    
}

@Model
class Team: Identifiable, Hashable {
    @Attribute(.unique) var id: UUID = UUID()
    var name: String
    var score: Int
    @Transient var editing: Bool = false
}

The .cascade argument to @Relationship tells SwiftData to delete all of the referenced Team objects if the CounterModel object is deleted.

Upvotes: 0

Related Questions