Post

Replies

Boosts

Views

Activity

SwiftData with CloudKit failing to migrate schema
My app has been in the App Store a few months. In that time I've added a few updates to my SwiftData schema using a MigrationPlan, and things were seemingly going ok. But then I decided to add CloudKit syncing. I needed to modify my models to be compatible. So, I added another migration stage for it, changed the properties as needed (making things optional or adding default values, etc.). In my tests, everything seemed to work smoothly updating from the previous version to the new version with CloudKit. So I released it to my users. But, that's when I started to see the crashes and error reports come in. I think I've narrowed it down to when users update from older versions of the app. I was finally able to reproduce this on my end, and Core Data is throwing an error when loading the ModelContainer saying "CloudKit integration requires that all attributes be optional, or have a default value set." Even though I did this in the latest schema. It’s like it’s trying to load CloudKit before performing the schema migration, and since it can’t, it just fails and won’t load anything. I’m kinda at a loss how to recover from this for these users other than tell them to delete their app and restart, but obviously they’ll lose their data that way. The only other idea I have is to setup some older builds on TestFlight and direct them to update to those first, then update to the newest production version and hope that solves it. Any other ideas? And what can I do to prevent this for future users who maybe reinstall the app from an older version too? There's nothing special about my code for loading the ModelContainer. Just a basic: let container = try ModelContainer( for: Foo.self, Bar.self, migrationPlan: SchemaMigration.self, configurations: ModelConfiguration(cloudKitDatabase: .automatic) )
5
3
2.1k
Jan ’24
SwiftData won't work with Measurement types
I'm trying out SwiftData and converting my existing data models using Structs and Codable to Classes and SwiftData. I've got a model that has a Measurement<UnitMass> type. When I run the app after converting everything to use classes with the @Model macro, I get a fatal error: SwiftData/SchemaProperty.swift:325: Fatal error: Unexpected type for CompositeAttribute: NSUnitMass. Since Measurement conforms to Codable, and SwiftData should work with Codable types, why is this not working? I also tried marking the property with @Attribute(.transformable) and it didn't make a difference.
11
13
3.8k
Jun ’23
SwiftData, Core Data, and initializing CloudKit development Schema
I recently discovered the new documentation for enabling CloudKit sync with SwiftData. A key step I was missing in my previous setup was this step: Initialize the CloudKit development schema. When I run this though, I get Core Data errors in my log... CoreData: Unsupported attribute type I've noticed that it seems to be preventing adding fields for my model properties that are Codable structs. I've been able to add Codable structs to my SwiftData models synced with CloudKit before. But using Core Data to initialize the CloudKit schema like the documentation suggests just doesn't work. Is there some other way around this? I'm about to just give up on CloudKit sync altogether. I need this to work because I'm trying to add some new fields and populate the fields with data based on existing data during the migration, but this seems to be preventing migration completely. If I don't initialize the schema, I get different errors and the ModelContainer won't initialize at all.
2
1
655
Apr ’24
SwiftData crash when setting child Model to parent
I've had a couple SwiftData crashes in production I can’t figure out. Both times the crash happened when setting a child Model to a parent Model. The child should already be inserted in the context before setting on the parent. But a crash still happens at CoreData: _PFManagedObject_coerceValueForKeyWithDescription. The child does have some Codable properties, but they’re just a couple enum. This isn’t a super common crash either. I can’t seem to reproduce. Any ideas? Simplified models: @Model final class Note { @Relationship(deleteRule: .nullify, inverse: \CoffeeBag.notes) var coffeeBag: CoffeeBag? } @Model final class CoffeeBag { var notes: [Note]? = [] } And the crash stack trace: Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: SIGNAL 6 Abort trap: 6 Terminating Process: MyApp [19953] Triggered by Thread: 0 Last Exception Backtrace: 0 CoreFoundation 0x1a2bbe678 __exceptionPreprocess + 164 (NSException.m:249) 1 libobjc.A.dylib 0x19ae63c80 objc_exception_throw + 60 (objc-exception.mm:356) 2 CoreData 0x1aad117a8 _PFManagedObject_coerceValueForKeyWithDescription + 1576 (NSManagedObject.m:0) 3 CoreData 0x1aad110e8 _sharedIMPL_setvfk_core + 180 (NSManagedObject_Accessors.m:1491) 4 SwiftData 0x23d9359c8 static _DefaultBackingData.setRelationship(value:key:managedObject:) + 360 (BackingData.swift:364) 5 SwiftData 0x23d9388fc closure #1 in static _DefaultBackingData.setValue(key:managedObject:newValue:) + 256 (BackingData.swift:215) 6 SwiftData 0x23d8d6e4c thunk for @callee_guaranteed () -> () + 28 (<compiler-generated>:0) 7 SwiftData 0x23d8d6e74 thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0) 8 CoreData 0x1aad087c4 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:3983) 9 CoreData 0x1aad08698 -[NSManagedObjectContext performBlockAndWait:] + 208 (NSManagedObjectContext.m:4094) 10 SwiftData 0x23d933758 static _DefaultBackingData.setValue(key:managedObject:newValue:) + 360 (BackingData.swift:211) 11 SwiftData 0x23d9383b0 _DefaultBackingData.setValue<A>(forKey:to:) + 232 (BackingData.swift:174) 12 SwiftData 0x23d93b328 protocol witness for BackingData.setValue<A>(forKey:to:) in conformance _DefaultBackingData<A> + 24 (<compiler-generated>:0) 13 SwiftData 0x23d8f32dc PersistentModel.setValue<A>(forKey:to:) + 288 (PersistentModel.swift:102) 14 MyApp 0x100f166d4 closure #1 in MyAppSchemaV6.Note.coffeeBag.setter + 132 (@__swiftmacro_7MyApp0aB8SchemaV6O4NoteC9coffeeBag18_PersistedPropertyfMa_.swift:15) 15 MyApp 0x100f22864 partial apply for closure #1 in MyAppSchemaV6.Note.coffeeBag.setter + 16 (<compiler-generated>:0) 16 libswiftObservation.dylib 0x247ff21b8 ObservationRegistrar.withMutation<A, B, C>(of:keyPath:_:) + 100 (ObservationRegistrar.swift:365) 17 MyApp 0x100f21c28 MyAppSchemaV6.Note.coffeeBag.setter + 172 (@__swiftmacro_7MyApp0aB8SchemaV6O4NoteC9coffeeBag18_PersistedPropertyfMa_.swift:14) 18 MyApp 0x100f21c28 closure #1 in closure #1 in closure #4 in BrewSummaryView.body.getter + 1076 (BrewSummaryView.swift:116) 19 SwiftUI 0x1a81b77b0 ButtonAction.callAsFunction() + 260 (Button.swift:598) // the rest is trimmed off to fit...
4
0
1.1k
Mar ’24
SwiftData Schema Migration crash in production
I've got an iOS app with SwiftData in production now. Not a huge amount of users, but decent amount. I'm using SwiftData to persist local "notes" or "logs" about data the user records while using the app for their own reference. So the data only lives on their device. So I recently made some changes to the models and it required using new schema versions. So I set up a SchemaMigrationPlan and tested it out locally and everything was working well. At the app root, I have this... init() { do { container = try ModelContainer( for: Foo.self, Bar.self, migrationPlan: MyAppSchemaMigration.self ) } catch { fatalError("Error migrating --- \(error.localizedDescription)") } } I've since received 10 crash reports over the past 2 weeks show up in Xcode Organizer from this fatalError, all from the same device. I'm unsure how to approach resolving this though, since the user hasn't reached out, so I can't provide direct support. This is definitely a tiny minority of people experiencing this crash, at least that are being reported. but it still makes me wonder if I could handle this better? And 10 crashes implies that relaunching the app isn't helping this person. What's the appropriate way to recover from this type of error? fatalError is so user unfriendly, but what else can you do in this situation? Would it be possible to somehow manually migrate? I can't just throw the data out and regenerate it because the data only lives on their device.
0
0
498
Dec ’23