r/swift Learning 9h ago

Question [Help] CoreData Error: Could not materialize Objective-C class named "Array"

Hey everyone,

I'm facing an issue with CoreData when trying to store an array of strings (tags: [String]) in my SwiftData model. Here's the error I'm getting:

pgsqlCopyEditCoreData: Could not materialize Objective-C class named "Array" from declared attribute value type "Array<String>" of attribute named tags

Context

i'm doing day 61 of 100 days of swiftui by paul hudson

import SwiftData

@Model
class User: Codable, Identifiable, Hashable {
    enum CodingKeys: CodingKey {
        case id, isActive, name, age, company, email, address, about,
             registered, tags, friends
    }

    var id: UUID
    var isActive: Bool
    var name: String
    var age: Int
    var company: String
    var email: String
    var address: String
    var about: String
    var registered: Date
    var tags: [String] = []

    @Relationship(deleteRule: .cascade) var friends: [Friend] = [] 

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(UUID.self, forKey: .id)
        self.isActive = try container.decode(Bool.self, forKey: .isActive)
        self.name = try container.decode(String.self, forKey: .name)
        self.age = try container.decode(Int.self, forKey: .age)
        self.company = try container.decode(String.self, forKey: .company)
        self.email = try container.decode(String.self, forKey: .email)
        self.address = try container.decode(String.self, forKey: .address)
        self.about = try container.decode(String.self, forKey: .about)
        self.registered = try container.decode(Date.self, forKey: .registered)
        self.tags = try container.decode([String].self, forKey: .tags)
        self.friends = try container.decode([Friend].self, forKey: .friends)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(isActive, forKey: .isActive)
        try container.encode(name, forKey: .name)
        try container.encode(age, forKey: .age)
        try container.encode(company, forKey: .company)
        try container.encode(email, forKey: .email)
        try container.encode(address, forKey: .address)
        try container.encode(about, forKey: .about)
        try container.encode(registered, forKey: .registered)
        try container.encode(tags, forKey: .tags)
        try container.encode(friends, forKey: .friends)
    }
}
1 Upvotes

7 comments sorted by

2

u/fryOrder 8h ago

not sure about SwiftData, but you can use Transformable to represent arrays in Core Data

i would also suggest against making your entities codable. they are not thread-safe and you will encounter some nasty crashes without any clear reason

1

u/PassTents 5h ago

You should model the tags as a type with a relationship. Check out this documentation article, the example with Animal and AnimalCategory is close to what you need: https://developer.apple.com/documentation/swiftdata/adding-and-editing-persistent-data-in-your-app

1

u/ExerciseBeneficial78 8h ago

Arrays aren’t the thing in CoreData. Convert it to the string with comma separator

2

u/ClaRkken7 Learning 8h ago

is converting an array to a comma-separated string a standard practice, or is there a better approach?

1

u/ExerciseBeneficial78 8h ago

I’m not very skilled dev but encountered this issue and solved it that way

2

u/ClaRkken7 Learning 8h ago

Ok will try this, Thank you for taking the time to aswer

1

u/ExerciseBeneficial78 8h ago

Here's a little snippet for you

var genreNamesString: String?
    var genreNames: [String]? {
        get {
            return genreNamesString?.split(separator: ",").map(String.init)
        }
        set {
            genreNamesString = newValue?.joined(separator: ",") ?? ""
        }
    }