I am creating an app and starting to try out SwiftData
for the first time in a app. I am going to post code so that y'all have has much info as possible.
First Question:
I am under the impression that if a model has a relationship to another model and that model has a relationship to another model you only need to include the first model in the container, not totally clear on that. I would like some clarification on that as well.
Second Question
I have my app setup for CloudKit and I get the following error when running:
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer)
If I turn off CloudKit under capabilities my app launches just fine. Heres my setup: I would like to know what I'm doing wrong.
Any anwsers to my 2 questions would be most appreciated.
**Models**
@Model
class ContactModel {
// MARK: - Properties
var anniversary: Date = Date.distantPast
var birthDay: Date = Date.distantPast
var firstName: String = ""
var lastName: String = ""
var streetAddress: String = ""
var city: String = ""
var state: String = ""
var postalCode: String = ""
var country: String = ""
var isoCountryCode: String = ""
var uniqueIDKey: String = ""
@Attribute(.externalStorage) var image: Data? = nil
// MARK: - Relationships
@Relationship(deleteRule: .cascade, inverse: \EventModel.contact)
var events: [EventModel]?
@Relationship(deleteRule: .nullify)
var crowd: CrowdModel?
init(
anniversary: Date,
birthDay: Date,
firstName: String,
lastName: String,
streetAddress: String,
city: String,
state: String,
postalCode: String,
country: String,
isoCountryCode: String,
uniqueIDKey: String,
image: Data? = nil,
events: [EventModel]? = nil,
crowd: CrowdModel? = nil
) {
self.anniversary = anniversary
self.birthDay = birthDay
self.firstName = firstName
self.lastName = lastName
self.streetAddress = streetAddress
self.city = city
self.state = state
self.postalCode = postalCode
self.country = country
self.isoCountryCode = isoCountryCode
self.uniqueIDKey = uniqueIDKey
self.image = image
self.events = events
self.crowd = crowd
}
}
@Model
class CrowdModel {
// MARK: - Properties
var name: String = ""
// MARK: - Relationships
@Relationship(deleteRule: .nullify, inverse: \ContactModel.crowd)
var contacts: [ContactModel]?
init(name: String, contacts: [ContactModel]? = nil) {
self.name = name
self.contacts = contacts
}
}
@Model
class EventModel {
var name: String = ""
var date: Date = Date.distantPast
var eventType: Int32 = 0
var notes: String = ""
// MARK: - Relationships
@Relationship(deleteRule: .cascade, inverse: \ReminderModel.event)
var reminders: [ReminderModel]?
@Relationship(deleteRule: .nullify)
var contact: ContactModel?
init(name: String, date: Date, eventType: Int32, notes: String, reminders: [ReminderModel]? = nil, contact: ContactModel? = nil) {
self.name = name
self.date = date
self.eventType = eventType
self.notes = notes
self.reminders = reminders
self.contact = contact
}
}
@Model
class ReminderModel {
// MARK: - Properties
var howManyDaysFrom: String = ""
var date: Date = Date.distantPast
var reminderID: String = ""
// MARK: - Relationships
@Relationship(deleteRule: .nullify)
var event: EventModel?
init(howManyDaysFrom: String, date: Date, reminderID: String, event: EventModel? = nil) {
self.howManyDaysFrom = howManyDaysFrom
self.date = date
self.reminderID = reminderID
self.event = event
}
}
**App Setup**
@main
struct EventPlannerApp: App {
// MARK: - Environment
@Environment(\.scenePhase) var scenePhase
@Environment(\.modelContext) var mc
// MARK: - SwiftData
let container: ModelContainer
init() {
let schema = Schema([ContactModel.self, CrowdModel.self, EventModel.self, ReminderModel.self])
let config = ModelConfiguration("EventPlanner", schema: schema)
do {
container = try ModelContainer(for: schema, configurations: config)
} catch {
fatalError("Couldn't load or configure container")
}
}
// MARK: - State
@State var jsonData = LoadJSONData()
@State var contactStore = ContactStore()
var body: some Scene {
WindowGroup {
MainAppView()
.environment(jsonData)
.environment(contactStore)
.onAppear {
// This suppresses constraint warnings
UserDefaults.standard.setValue(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
}
.defaultAppStorage(UserDefaults(suiteName: AC.appGroup.rawValue)!)
}
.modelContainer(container)
.onChange(of: scenePhase) {
switch scenePhase {
case .background:
#warning("Add code to save database and delete break statement")
break
case .active, .inactive:
break
@unknown default:
fatalError("fatal error for .onChange(of: scenePhase) modifier")
}
}
}
}