Now I am working to make a Question and Answer App. for medical student using Swift Data. I am tryin to make a class for Question type and another class Q for item in Question type. Then I added the @Model macro the make a structure. This app class and says "Failed to find any currently loaded container for Q I made the class q codable but it also clash And says
"SwiftData/ModelContainer.swift:144: Fatal error: failed to find a currently active container for Q Failed to find any currently loaded container for Q)"
I have made a simple code to recreate the crush like below
import SwiftUI
import SwiftData
@main
struct MyApp: App {
let modelContainer: ModelContainer
@State private var appData = ApplicationData()
init() {
do {
modelContainer = try ModelContainer(for: Question.self)
} catch {
fatalError("Could not initialize ModelContainer")
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(modelContainer)
}
}
import SwiftUI
import Observation
import SwiftData
@Observable class ApplicationData {
var viewPath = NavigationPath()
var userData: [Question]
init() {
userData =
[
Question(qid: "230272", year: "2023", q: [Q(qid:"1", q: "1.대인관계치료"), Q(qid:"2", q: "2. 사회기술재활"), Q(qid:"3", q: "3. 습관역전훈련"), Q(qid:"4",q: "4.변증법적행동치료"), Q(qid:"5", q: "5.안구운동탈민감재처리")]),
Question(qid: "230273", year: "2023", q: [Q(qid:"1", q: "1.홍수법"), Q(qid:"2", q: "2.수면제한"), Q (qid: "3", q: "3.동기강화치료"), Q(qid:"4", q: "4.체계적 탈감작"), Q( qid: "5", q: "5.노출과 반응차단")])
]
}
}
@Model
class Question: Identifiable {
@Attribute(.unique) var idid: UUID = UUID()
var qid : String = ""
var year: String = ""
var q: [Q?] = []
init( qid: String, year: String, q: [Q?]) {
self.qid = qid
self.year = year
self.q = q
}
}
@Model
class Q: Identifiable, Codable {
enum CodingKeys: CodingKey {
case qid, q
}
@Attribute(.unique) var id = UUID()
var qid: String? = ""
var q: String? = ""
init( qid: String?, q: String?) {
// self.id = UUID().uuidString
self.qid = qid
self.q = q
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.qid = try container.decode(String.self, forKey: .qid)
self.q = try container.decode(String.self, forKey: .q)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(qid, forKey: .qid)
try container.encode(q, forKey: .q)
}
}
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(ApplicationData.self) private var appData
@Environment(\.modelContext) var dbContext
@Query var listQuestions: [Question]
var body: some View {
NavigationStack(path: Bindable(appData).viewPath) {
List(listQuestions) { question in
CellQuestion(question: question)
}
.listStyle(.plain)
.navigationTitle("Title")
.toolbarTitleDisplayMode(.inline)
}
}
}
struct CellQuestion: View {
let question: Question
var body: some View {
Text(question.year)
}
}
There are a few errors in your code.
Solution here is to move the code inside the init into a separate function and call that function from an onAppear
Pass the model context as a parameter to the function in 1.
add .environment(appData)
to WindowGroup
in main
Here is my simplified implementation of ApplicationData
@Observable class ApplicationData {
var viewPath = NavigationPath()
init() {}
func load(modelContext: ModelContext) {
let q1 = Question(qid: "230272", year: "2023", q: [QuestItem(qid:"1", q: "1.대인관계치료"), QuestItem(qid:"2", q: "2. 사회기술재활"), QuestItem(qid:"3", q: "3. 습관역전훈련"), QuestItem(qid:"4",q: "4.변증법적행동치료"), QuestItem(qid:"5", q: "5.안구운동탈민감재처리")])
modelContext.insert(q1)
let q2 = Question(qid: "230273", year: "2023", q: [QuestItem(qid:"1", q: "1.홍수법"), QuestItem(qid:"2", q: "2.수면제한"), QuestItem (qid: "3", q: "3.동기강화치료"), QuestItem(qid:"4", q: "4.체계적 탈감작"), QuestItem( qid: "5", q: "5.노출과 반응차단")])
modelContext.insert(q2)
}
}
And the ContentView where the call to load(...)
should be assigned to a button rather then being executed everytime but this view code only serves as an example,
struct ContentView: View {
@Environment(ApplicationData.self) private var appData
@Environment(\.modelContext) var dbContext
@Query var listQuestions: [Question]
var body: some View {
NavigationStack(path: Bindable(appData).viewPath) {
List(listQuestions) { question in
CellQuestion(question: question)
}
.onAppear {
appData.load(modelContext: dbContext)
}
}
}
}