SwiftData, @Model, and the 'conform to PersistentModel' error

I am stumbling and would appreciate any insight. Am writing first app and utilizing SwiftData. In first iteration I created the following model that builds and functions correctly.


@Model
class Player: Identifiable {
    
    @Attribute(.unique)  var id: String
    var name: String
    
    init(){
        id = UUID().uuidString
        name = "......"
    }    
}

This was encouraging. However, when I ‘enhanced’ my model by adding a new variable with a type based on a defined structure , the build fails with error that the struct does not conform to PersistentModel. Here is the code.

@Model
class Player: Identifiable {  
    @Attribute(.unique)  var id: String
    var name: String
    var lastParams: RoundParam
    
    init(){
        id = UUID().uuidString
        name = "......"
        lastParams = RoundParam()
    }   
}


struct RoundParam {
    var nDots = 3
    var seqLen = 3
    var repeatDots = false
    var shuffleDots = false
    var durOn = 0.5
    var durGap = 0.5
    var durResponse = 5.0 
}

Would greatly appreciate any insight in to what I am missing.

Thank you !!!

I believe have solved my own question. It seems the Models can not include ‘struct’ but do accept other Model class objects. Below is the code that does successfully build.

@Model
class Player: Identifiable {
    
    @Attribute(.unique)  var id: String
    var name: String
    var lastParams: RoundParam?
    
    init(){
        id = UUID().uuidString
        name = "......"
        lastParams = RoundParam()
    }
    
}


@Model
class RoundParam {
    
    var nDots: Int
    var seqLen: Int
    var repeatDots: Bool
    var shuffleDots: Bool
    var durOn: Double
    var durGap: Double
    var durResponse: Double
    
    init() {
        nDots = 3
        seqLen = 3
        repeatDots = false
        shuffleDots = false
        durOn = 0.5
        durGap = 0.5
        durResponse = 5.0
    }
    
}

Thanks for taking time to review. Hope this is of some use to other newbies.

Regards

I was about to respond to your question with exactly that so well done.

@bobaronoff

Hi Robert,

Did you figure out what you needed to do to get the delete process to work so that it cascaded from the Player to the RoundParam? Using your data model I found it a little tricky so I would be curious to know what you ended up with in terms of the @Model in each case.

Chris,

Thank you for your help. In this use case am not looking to cascade from Player to RoundParam. The intent is to store a single instance of RoundParam as a property in each instance of Player. The initial code attempt had RoundParam as a ‘struct’ but that does not build so through trial and error I made it a @Model/class. I do not foresee inserting any data in to RoundParam, am just using it as means to insert an instance in to Player. I will not need to cascade any delete from Player.

Still don’t fully understand why a struct type can not be used as a @Model property type but accept that is the way it is.

Am still conceptually sorting things out. Have tendency to think in SQL terms i.e., @Model/class as a ‘table schema’, properties as fields, and @Relationship as a ‘join’. Am appreciating that this analogy has it’s limits :slightly_smiling_face:

regards,
Bob

Okay, think I figured out why using a struct type as a model property type was not building !

The struct type must be declared conforming to the ‘Codable’ protocol. Makes sense, data is stored as JSON ‘under the hood’.

Here is code that is working:

import SwiftData


struct RoundParam: Codable {
    
    var nDots: Int = 3
    var seqLen: Int = 3
    var repeatDots: Bool = false
    var shuffleDots: Bool = false
    var durOn: Double = 0.5
    var durGap: Double = 0.5
    var durResponse: Double = 5.0
   
}

@Model
class Player: Identifiable {
    
    @Attribute(.unique)  var id: String
    var name: String
    var lastParams: RoundParam
    
    init(){
        id = UUID().uuidString
        name = "......"
        lastParams = RoundParam()
    }
    
}

It’s always the ‘little things’ - lol

Interesting solution. I had not considered that making the RoundParam struct conform to Codable would be automatically dealt with in the background.

You learn something every day.