Thread 1: "Model already contains an entity named <member>."

I'm trying to store a few classes using SwiftData, but I am getting the error mentioned in the title. The classes I'm trying to store can be found at https://github.com/jmshrv/wanikani-swift/blob/swiftdata/Sources/WaniKani/Models/Subject.swift. Specifically, I'm trying to store the Radical, Kanji, Vocabulary, and KanaVocabulary types.

I think this issue has something to do with the classes having members with the same name and data type, but I can't reproduce this, so that mustn't be the case. Has anyone else run into this?

Answered by jmsharvey771 in 758688022

A workaround for this is to specify a ModelConfiguration that uses a different database file for each type. My solution is based off the example code shown in wwdc2023-10196. It should be noted that the example code fails with the error "Cannot use instance member '<member>' within property initializer; property initializers run before 'self' is available", so I had to move the ModelContainer initialisation into .modelContainer.

import SwiftUI
import SwiftData

@main
struct TestApp: App {
    let fullSchema = Schema([
        Item.self,
        DuplicateItem.self
    ])
    
    let itemModelConfiguration = ModelConfiguration(
        schema: Schema([
            Item.self
        ]),
        url: URL.applicationSupportDirectory.appendingPathComponent("item.store")
    )
    
    let duplicateItemModelConfiguration = ModelConfiguration(
        schema: Schema([
            DuplicateItem.self
        ]),
        url: URL.applicationSupportDirectory.appendingPathComponent("duplicateItem.store")
    )

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(try! ModelContainer(for:
            fullSchema,
            itemModelConfiguration,
            duplicateItemModelConfiguration)
        )
    }
}

I've got a minimal reproduction working.

@Model
class Item {
    var test: [Int]
    
    init(test: [Int]) {
        self.test = test
    }
}

@Model
class DuplicateItem {
    var test: [Int]
    
    init(test: [Int]) {
        self.test = test
    }
}

Internally, SwiftData makes an SQL database and adds a table called Z<MEMBER>. It tries to make this twice, and fails.

Accepted Answer

A workaround for this is to specify a ModelConfiguration that uses a different database file for each type. My solution is based off the example code shown in wwdc2023-10196. It should be noted that the example code fails with the error "Cannot use instance member '<member>' within property initializer; property initializers run before 'self' is available", so I had to move the ModelContainer initialisation into .modelContainer.

import SwiftUI
import SwiftData

@main
struct TestApp: App {
    let fullSchema = Schema([
        Item.self,
        DuplicateItem.self
    ])
    
    let itemModelConfiguration = ModelConfiguration(
        schema: Schema([
            Item.self
        ]),
        url: URL.applicationSupportDirectory.appendingPathComponent("item.store")
    )
    
    let duplicateItemModelConfiguration = ModelConfiguration(
        schema: Schema([
            DuplicateItem.self
        ]),
        url: URL.applicationSupportDirectory.appendingPathComponent("duplicateItem.store")
    )

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(try! ModelContainer(for:
            fullSchema,
            itemModelConfiguration,
            duplicateItemModelConfiguration)
        )
    }
}
Thread 1: "Model already contains an entity named &lt;member&gt;."
 
 
Q