Post

Replies

Boosts

Views

Activity

Migrating a Transformable attribute from CoreData to SwiftData
I am migrating a CloudKit-synchronized multi-platform app from CoreData to SwiftData. (Xcode 27.0 beta 5). One of my Models/Entities contains a Transformable attribute, which is defined in the CoreData model editor as: and which is defined in the generated CoreData class as @NSManaged nonisolated public var authorNames: [String]? Using the built-in translation took, Xcode created a Model wich included @Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformerName")) var authorNames: [String] = [] This compiles but does not run. In the function func getModelContainer() throws -> ModelContainer { let storeURL = try FileManager.default.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent(dbName) let modelConfiguration = ModelConfiguration( schema: dbSchema, url: storeURL, cloudKitDatabase: .automatic) let container = try ModelContainer( for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) return container } the app throws a fatal error in the ModelContainer initializer, SwiftData/SchemaCoreData.swift:398: Fatal error: Application must register a ValueTransformer for NSSecureUnarchiveFromDataTransformerName So I added the following line of code at the top of this function: ValueTransformer.setValueTransformer( NSSecureUnarchiveFromDataTransformer(), forName: .secureUnarchiveFromDataTransformerName) which also compiles but also throws the same fatal error in the same place. Can anyone suggest how to resolve this problem? This is a CloudKit synchronized app, so I am constrained in what I can do with this attribute.
1
0
173
3w
How do I write this #Predicate?
I have two Models which are defined (simplified) as follows: @Model final class Book { var id: UUID = UUID() var title: String = "" var authors: [Author]? = [] } @Model final class Author { var id: UUID = UUID() var name: String "" @Relationship(inverse: \Book.authors) var books: [Book]? = [] } Both Book.authors and Author.books are defined as optionals to satisfy the requirements of CloudKit, although it is clear from the above that neither is ever actually nil. I am trying to write a #Predicate that finds objects of type Book with a title that matches a specified title and with an author that matches a specified author. The function I'd like to write looks something like this: func find(title: String, author: Author, with context: ModelContext) -> Book? { let same = ComparisonResult.orderedSame let predicate = #Predicate<Book> { book in book.title.caseInsensitiveCompare(title) == same && book.authors!.contains(where: { $0.id == author.id }) } let descriptor = FetchDescriptor<Book>(predicate: predicate) return try? context.fetch(descriptor).first } This function fails to compile inside the expansion of the #Predicate macro with a very long error message: Cannot convert value of type (a long 'PredicateExpresions....') (aka (another log 'PredicateExpressions....')) to closure result type 'any StandardPredicateExpression<Bool>' I don't understand. How can I write this predicate so that it will both compile and work? I know how to work around this problem, but would like to both deepen my understanding of Swift and SwiftData and to avoid the (inelegant) workaround.
2
0
374
3w
CoreDate->SwiftData Migration & CloudKit
I have an existing CoreData + CloudKit app which I would like to migrate to SwiftData + CloudKit. In the existing CoreData implementation, I have many optional fields (most of which have default values). I want to migrated them to SwiftData non-optional fields with default values. Can someone please confirm that I can do this without causing issues for my existing (CoreData + CloudKit) customers? I.e., I know I can do the migration on the local copy of the database, but I am worried about the CloudKit interaction. Specifically, I'm concerned about properties such as var title: String? which is implemented in CloudKit as CD_title CD_title_ckAsset Can I safely implement this in SwiftData as var title: String = "" without causing a problem with the CloudKit implementation?
1
0
592
Aug ’26
MacCatalyst and Image of AppIcon
In my apps, I have a requirement to display an image of the application icon is certain circumstances. This is fairly straightforward for iOS/iPadOS and it used to be straightforward for macCatalyst. For MacCatalyst, this is no longer true (at least since macOS 26). This is because the app icon is now stored as an .icns file and (in the case of using an IconComposer icon), the `'png' in the Asset Catalog now has an unknown name. So the following code no longer works: public extension Bundle { var icon: UIImage? { #if targetEnvironment(macCatalyst) guard let iconName = infoDictionary?["CFBundleIconName"] as? String else { return nil } return UIImage(named: iconName, in: self, compatibleWith: nil) #else guard let icons = infoDictionary?["CFBundleIcons"] as? [String : Any] else { return nil } guard let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String : Any] else { return nil } guard let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String] else { return nil } guard let file = iconFiles.last else { return nil } return UIImage(named: file, in: self, compatibleWith: nil) #endif } The obvious solution is to place an Image in the Asset Catalog which I can access, but this is a maintenance headache. What I would actually like to do is either create a UIImage directly from the .icns file, or access the .png file in the Asset Catalog (which has a name beginning with the icon file name, but has additional characters in its name that I don't know). Can you help?
3
0
924
Aug ’26
Handling SwiftData Initialization Errors
The traditional way to initialize a SwiftData app looks like some variation of the following: @main struct TrainingCornerApp: App { let dbSchema: Schema = ... init() { } var body: some Scene { WindowGroup { MainAppScreen() .modelContainer(modelContainer) } } } private var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false, cloudKitDatabase: .automatic) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to create model container: \(error.localizedDescription)") } return container } } That is, if creating the modelContainer fails, the app aborts with a fatalError. What I want to do is have the application present an alert message for the user before terminating. (Let the user know the app can't run and suggest how to get help -- that sort of thing.) However, I've been having a hard time getting this to work, and it seems that the problems are related to trying to generate the alert at such an early stage in app startup. Does anyone have ideas/suggestions on how I might do this?
0
0
479
Aug ’26
SwiftData, CloudKit and 2 AppleIDs
I have a SwiftData app that runs on iOS, iPadOS, and MacCatalyst and which uses CloudKit for inter-device sync. Unfortunately, I also have two AppleIDs (which I 'll refer to as OLDID and NEWID). Although all three devices (phone, pad and desktop) are currently set up with NEWID as the active AppleID, during development and testing, my desktop Mac used OLDID. Apparently, the system remembers the AppleID to use with each CloudKit app (based on the AppleID active at time of first use), because the desktop app and the mobile apps apparently sync to different AppleID accounts. I can delete the local database on the desktop and delete the local app on the mobile devices and in each case, reloading/rerunning the app causes the respective databases to be restored from the cloud. The two mobile devices sync with each other, but not with the desktop; the desktop doesn't sync with either device. And the two databases have decidedly different contents. My goal is to consolidate everything so that there is one database, shared and synced between desktop, pad, phone and cloud. I presume that there is a setting somewhere (but clearly NOT in the app's sandboxed container) that specifies what iCloud account to use for that (and each) app. Note: I have other apps which sync between all my devices, so the setting must be on a per-app basis. I also presume that if I changed it's value on my desktop (so that all three devices used the same AppleID for cloud services for my app), that the content of the local database on my desktop would be synced automatically to the NEWID cloud account and then (also automatically) synchronized with my mobile devices. I.e., I speculate that I can solve all my problems by changing that setting on my desktop Mac. So I have two questions: Is all this correct? How do I make this setting change. (I.e., where is it and how do I change it) Does anyone have any experience and can help with this issue? Thanks
3
0
1.2k
Jun ’26
SwiftData @Query with a Custom (non-standard) Sort Criterion
I have a @Query which I would like to sort using a custom criterion. I would like to use an array of SortDescriptors where I can specify a key path and a CUSTOM SortComparator. (I.e., I can write SortComparators which do what I want, but I can't use them in a SortDescriptor because there is no initializer which takes a SortCompartor which is not a String.StandardComparator.) This is not a question about dynamic sorting, which has well-known solutions. I am trying to perform a sort which cannot be satisfied by any existing SortDescriptor (or array of SortDescriptors). Any thoughts about how to resolve this situation?
2
0
940
Jun ’26
SwiftData 'simple' migration failing
This is a long post, so let me start with a summary: I am attempting to implement what "ought to be" a simple SwiftData migration, and am receiving the following fatal error from the ModelContainer initializer: NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." The crash occurs both in the Simulator and on a physical device. Both the original schema and the new schema load and run as expected if loaded from scratch — so I conclude the Models are OK; it is the migration from the original schema to the new schema which is the issue. I have reported this as FB22652791 and Technical Incident Case # 19893980. I have two model projects available — one contrived, the other using my actual SwiftData models. Now the Details I am developing a SwiftUI/SwiftData app. I am (currently) using Xcode 26.5-beta-3. I set up an alpha-test build using the following approach: public class DatabaseSchema { public let dbSchema: Schema = Schema([ Model1.self, ... , Model16.self ], version: Schema.Version(0, 9, 0)) public var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false) do { container = try ModelContainer(for: dbSchema, migrationPlan: nil, configurations: [modelConfiguration]) } catch { fatalError("Failed to creae model conainer") } return container } This defines database version 0.9. For version 1.0, I made three changes to the database: added an attribute of type String to Model2. added three attributes of type [Struct], where Struct conforms to Codable, Equatable and Hashable to Model3, and added a new model (which I'll call Model17) I define two schemas: public enum Schema090: VersionedSchema { public static var versionIdentifier = Schema.Version(0, 9, 0) public static var models: [any PersistentModel.Type] = [ Model1.self, Schema090.Model2.self, Schema090.Model3.self, ... ] } and public enum Schema100: VersionedSchema { public static var versionIdentifier = Schema.Version(1, 0, 0) public static var models: [any PersistentModel.Type] = [ Model1.swift, Schema100.Model2.self, Schema100.Model3.self, ..., Model16.self, Schema100.Model17.self ] } For models that changed, I use the following approach: public typealias Model3 = Schema100.Model3 extension Schema090 { @Model final class Model3 { ... } public init() { ... } } extension Schema100 { @Model final class Model3 { ... <added attributes, initialized> } public init() { ... } } The DatabaseSchema class was modified as follows: public class DatabaseSchema { public let dbSchema: Schema = Schema([ Model1.self, Schema100.Model2.self, Schema100.Model3.self, ... , Model16.self, Schema100.Model17.self ], version: Schema.Version(1, 0, 0)) public var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to creae model conainer") } return container } where the migration plan is the trivial custom migration that makes sure that all added attributes of existing records are properly initialized. enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] = [ Schema090.self, Schema100.self ] static var stages: [MigrationStage] = [version090ToVersion100] static let version090ToVersion100 = MigrationStage(fromVersion: Schema090.self, toVersion: Schema100.self, willMigrate: { _ in }, didMigrate: { context in let models = try context.fetch( FetchDescriptor<Schema100.Model3>()) for model in models { < initial the added attributes > { try context.save() }) } This is all simple stuff. Nothing particularly fancy here. But running this code always crashes in the ModelContainer initializer. In my two sample projects, I get two different error messages — in the contrived example, the error message is Code=134110 "An error occurred during persistent store migration." reason=Cannot migrate store in-place: Validation error missing attribute values on mandatory destination attribute, ... and in the sample project that uses my actual data model, I get NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." My Thoughts Since obviously most folks are doing SwiftData migrations without the problems I am experiencing, the obvious possibilities are I'm doing something stupid that I just don't see. There is a problem because the original schema was given a version value of Schema.Version(0, 9, 0). (i.e., major version number was 0) There is a problem because I am adding an attribute of type [Struct] where Struct is Codable, Hashable, and Equatable. I.e., migration isn't working properly with attributes which are stored as their codable representations. Or maybe something else? In any case, any help you can offer would be greatly appreciated.
7
0
1.5k
Jun ’26
Using @Environment with TabView
Let me ask the general question first, then explain the context... Each Tab of a TabView defines a separate View hierarchy. (I'm assuming that the root view of each Tab defines its own NavigationStack.) Since an @Environment is supposed to serve data to the child views in its view hierarchy, does this mean that it is possible to define Environments in each tab's root view with the same name (i.e. key) but different values? (I.e., I want a subview to access an environment value for the current view hierarchy without requiring that the subview have any knowledge of which hierarchy it is being called from.) The actual use case has to do with using @Environment in a tabbed application to inject a router in subviews. (Each Tab has its own NavigationStack and its own NavigationPath.) I have an @Observable router class which manages a NavigationPath.. The root view of each Tab in the application has its own instance of that router object (and hence, it's own NavigationPath). I want to inject that router into all of the subviews in each Tab's view hierarchy, so that I can use path-based navigation. My current implementation injects the router throughout the view hierarchies via constructor injection. This works, but is a real pain and includes a bunch of duplicate code. I would like to use @Environment injection instead, but this can only work if @Environment stores its EnvironmentValues on a per view-hierarchy (rather than a per-application) basis. So, can this approach work? what experience can you share concerting router-based navigation in a TabView-based app? Thanks.
2
0
383
Jan ’26
MacCatalyst and the User's Documents Folder
I have a SwiftUI-based universal app which creates a file that it stores in documentsDirectory. On iOS/iPadOS, this file is stored in the application's Documents directory and is accessible via the Files app. On MacCatalyst, this operation does the same thing — it creates the file and stores it in ~/Library/Containers/<app directory>/Data/Documents. However what I want is for the document to be stored in ~/Documents, so that it is easily accessible to the user. How can I do that? I'd like it to occur without (for example) having to show a SaveFile panel...
4
0
1.2k
Dec ’25
Migrating a Transformable attribute from CoreData to SwiftData
I am migrating a CloudKit-synchronized multi-platform app from CoreData to SwiftData. (Xcode 27.0 beta 5). One of my Models/Entities contains a Transformable attribute, which is defined in the CoreData model editor as: and which is defined in the generated CoreData class as @NSManaged nonisolated public var authorNames: [String]? Using the built-in translation took, Xcode created a Model wich included @Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformerName")) var authorNames: [String] = [] This compiles but does not run. In the function func getModelContainer() throws -> ModelContainer { let storeURL = try FileManager.default.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent(dbName) let modelConfiguration = ModelConfiguration( schema: dbSchema, url: storeURL, cloudKitDatabase: .automatic) let container = try ModelContainer( for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) return container } the app throws a fatal error in the ModelContainer initializer, SwiftData/SchemaCoreData.swift:398: Fatal error: Application must register a ValueTransformer for NSSecureUnarchiveFromDataTransformerName So I added the following line of code at the top of this function: ValueTransformer.setValueTransformer( NSSecureUnarchiveFromDataTransformer(), forName: .secureUnarchiveFromDataTransformerName) which also compiles but also throws the same fatal error in the same place. Can anyone suggest how to resolve this problem? This is a CloudKit synchronized app, so I am constrained in what I can do with this attribute.
Replies
1
Boosts
0
Views
173
Activity
3w
How do I write this #Predicate?
I have two Models which are defined (simplified) as follows: @Model final class Book { var id: UUID = UUID() var title: String = "" var authors: [Author]? = [] } @Model final class Author { var id: UUID = UUID() var name: String "" @Relationship(inverse: \Book.authors) var books: [Book]? = [] } Both Book.authors and Author.books are defined as optionals to satisfy the requirements of CloudKit, although it is clear from the above that neither is ever actually nil. I am trying to write a #Predicate that finds objects of type Book with a title that matches a specified title and with an author that matches a specified author. The function I'd like to write looks something like this: func find(title: String, author: Author, with context: ModelContext) -> Book? { let same = ComparisonResult.orderedSame let predicate = #Predicate<Book> { book in book.title.caseInsensitiveCompare(title) == same && book.authors!.contains(where: { $0.id == author.id }) } let descriptor = FetchDescriptor<Book>(predicate: predicate) return try? context.fetch(descriptor).first } This function fails to compile inside the expansion of the #Predicate macro with a very long error message: Cannot convert value of type (a long 'PredicateExpresions....') (aka (another log 'PredicateExpressions....')) to closure result type 'any StandardPredicateExpression<Bool>' I don't understand. How can I write this predicate so that it will both compile and work? I know how to work around this problem, but would like to both deepen my understanding of Swift and SwiftData and to avoid the (inelegant) workaround.
Replies
2
Boosts
0
Views
374
Activity
3w
CoreDate->SwiftData Migration & CloudKit
I have an existing CoreData + CloudKit app which I would like to migrate to SwiftData + CloudKit. In the existing CoreData implementation, I have many optional fields (most of which have default values). I want to migrated them to SwiftData non-optional fields with default values. Can someone please confirm that I can do this without causing issues for my existing (CoreData + CloudKit) customers? I.e., I know I can do the migration on the local copy of the database, but I am worried about the CloudKit interaction. Specifically, I'm concerned about properties such as var title: String? which is implemented in CloudKit as CD_title CD_title_ckAsset Can I safely implement this in SwiftData as var title: String = "" without causing a problem with the CloudKit implementation?
Replies
1
Boosts
0
Views
592
Activity
Aug ’26
MacCatalyst and Image of AppIcon
In my apps, I have a requirement to display an image of the application icon is certain circumstances. This is fairly straightforward for iOS/iPadOS and it used to be straightforward for macCatalyst. For MacCatalyst, this is no longer true (at least since macOS 26). This is because the app icon is now stored as an .icns file and (in the case of using an IconComposer icon), the `'png' in the Asset Catalog now has an unknown name. So the following code no longer works: public extension Bundle { var icon: UIImage? { #if targetEnvironment(macCatalyst) guard let iconName = infoDictionary?["CFBundleIconName"] as? String else { return nil } return UIImage(named: iconName, in: self, compatibleWith: nil) #else guard let icons = infoDictionary?["CFBundleIcons"] as? [String : Any] else { return nil } guard let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String : Any] else { return nil } guard let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String] else { return nil } guard let file = iconFiles.last else { return nil } return UIImage(named: file, in: self, compatibleWith: nil) #endif } The obvious solution is to place an Image in the Asset Catalog which I can access, but this is a maintenance headache. What I would actually like to do is either create a UIImage directly from the .icns file, or access the .png file in the Asset Catalog (which has a name beginning with the icon file name, but has additional characters in its name that I don't know). Can you help?
Replies
3
Boosts
0
Views
924
Activity
Aug ’26
Handling SwiftData Initialization Errors
The traditional way to initialize a SwiftData app looks like some variation of the following: @main struct TrainingCornerApp: App { let dbSchema: Schema = ... init() { } var body: some Scene { WindowGroup { MainAppScreen() .modelContainer(modelContainer) } } } private var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false, cloudKitDatabase: .automatic) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to create model container: \(error.localizedDescription)") } return container } } That is, if creating the modelContainer fails, the app aborts with a fatalError. What I want to do is have the application present an alert message for the user before terminating. (Let the user know the app can't run and suggest how to get help -- that sort of thing.) However, I've been having a hard time getting this to work, and it seems that the problems are related to trying to generate the alert at such an early stage in app startup. Does anyone have ideas/suggestions on how I might do this?
Replies
0
Boosts
0
Views
479
Activity
Aug ’26
SwiftData, CloudKit and 2 AppleIDs
I have a SwiftData app that runs on iOS, iPadOS, and MacCatalyst and which uses CloudKit for inter-device sync. Unfortunately, I also have two AppleIDs (which I 'll refer to as OLDID and NEWID). Although all three devices (phone, pad and desktop) are currently set up with NEWID as the active AppleID, during development and testing, my desktop Mac used OLDID. Apparently, the system remembers the AppleID to use with each CloudKit app (based on the AppleID active at time of first use), because the desktop app and the mobile apps apparently sync to different AppleID accounts. I can delete the local database on the desktop and delete the local app on the mobile devices and in each case, reloading/rerunning the app causes the respective databases to be restored from the cloud. The two mobile devices sync with each other, but not with the desktop; the desktop doesn't sync with either device. And the two databases have decidedly different contents. My goal is to consolidate everything so that there is one database, shared and synced between desktop, pad, phone and cloud. I presume that there is a setting somewhere (but clearly NOT in the app's sandboxed container) that specifies what iCloud account to use for that (and each) app. Note: I have other apps which sync between all my devices, so the setting must be on a per-app basis. I also presume that if I changed it's value on my desktop (so that all three devices used the same AppleID for cloud services for my app), that the content of the local database on my desktop would be synced automatically to the NEWID cloud account and then (also automatically) synchronized with my mobile devices. I.e., I speculate that I can solve all my problems by changing that setting on my desktop Mac. So I have two questions: Is all this correct? How do I make this setting change. (I.e., where is it and how do I change it) Does anyone have any experience and can help with this issue? Thanks
Replies
3
Boosts
0
Views
1.2k
Activity
Jun ’26
SwiftData @Query with a Custom (non-standard) Sort Criterion
I have a @Query which I would like to sort using a custom criterion. I would like to use an array of SortDescriptors where I can specify a key path and a CUSTOM SortComparator. (I.e., I can write SortComparators which do what I want, but I can't use them in a SortDescriptor because there is no initializer which takes a SortCompartor which is not a String.StandardComparator.) This is not a question about dynamic sorting, which has well-known solutions. I am trying to perform a sort which cannot be satisfied by any existing SortDescriptor (or array of SortDescriptors). Any thoughts about how to resolve this situation?
Replies
2
Boosts
0
Views
940
Activity
Jun ’26
SwiftData 'simple' migration failing
This is a long post, so let me start with a summary: I am attempting to implement what "ought to be" a simple SwiftData migration, and am receiving the following fatal error from the ModelContainer initializer: NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." The crash occurs both in the Simulator and on a physical device. Both the original schema and the new schema load and run as expected if loaded from scratch — so I conclude the Models are OK; it is the migration from the original schema to the new schema which is the issue. I have reported this as FB22652791 and Technical Incident Case # 19893980. I have two model projects available — one contrived, the other using my actual SwiftData models. Now the Details I am developing a SwiftUI/SwiftData app. I am (currently) using Xcode 26.5-beta-3. I set up an alpha-test build using the following approach: public class DatabaseSchema { public let dbSchema: Schema = Schema([ Model1.self, ... , Model16.self ], version: Schema.Version(0, 9, 0)) public var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false) do { container = try ModelContainer(for: dbSchema, migrationPlan: nil, configurations: [modelConfiguration]) } catch { fatalError("Failed to creae model conainer") } return container } This defines database version 0.9. For version 1.0, I made three changes to the database: added an attribute of type String to Model2. added three attributes of type [Struct], where Struct conforms to Codable, Equatable and Hashable to Model3, and added a new model (which I'll call Model17) I define two schemas: public enum Schema090: VersionedSchema { public static var versionIdentifier = Schema.Version(0, 9, 0) public static var models: [any PersistentModel.Type] = [ Model1.self, Schema090.Model2.self, Schema090.Model3.self, ... ] } and public enum Schema100: VersionedSchema { public static var versionIdentifier = Schema.Version(1, 0, 0) public static var models: [any PersistentModel.Type] = [ Model1.swift, Schema100.Model2.self, Schema100.Model3.self, ..., Model16.self, Schema100.Model17.self ] } For models that changed, I use the following approach: public typealias Model3 = Schema100.Model3 extension Schema090 { @Model final class Model3 { ... } public init() { ... } } extension Schema100 { @Model final class Model3 { ... <added attributes, initialized> } public init() { ... } } The DatabaseSchema class was modified as follows: public class DatabaseSchema { public let dbSchema: Schema = Schema([ Model1.self, Schema100.Model2.self, Schema100.Model3.self, ... , Model16.self, Schema100.Model17.self ], version: Schema.Version(1, 0, 0)) public var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to creae model conainer") } return container } where the migration plan is the trivial custom migration that makes sure that all added attributes of existing records are properly initialized. enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] = [ Schema090.self, Schema100.self ] static var stages: [MigrationStage] = [version090ToVersion100] static let version090ToVersion100 = MigrationStage(fromVersion: Schema090.self, toVersion: Schema100.self, willMigrate: { _ in }, didMigrate: { context in let models = try context.fetch( FetchDescriptor<Schema100.Model3>()) for model in models { < initial the added attributes > { try context.save() }) } This is all simple stuff. Nothing particularly fancy here. But running this code always crashes in the ModelContainer initializer. In my two sample projects, I get two different error messages — in the contrived example, the error message is Code=134110 "An error occurred during persistent store migration." reason=Cannot migrate store in-place: Validation error missing attribute values on mandatory destination attribute, ... and in the sample project that uses my actual data model, I get NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." My Thoughts Since obviously most folks are doing SwiftData migrations without the problems I am experiencing, the obvious possibilities are I'm doing something stupid that I just don't see. There is a problem because the original schema was given a version value of Schema.Version(0, 9, 0). (i.e., major version number was 0) There is a problem because I am adding an attribute of type [Struct] where Struct is Codable, Hashable, and Equatable. I.e., migration isn't working properly with attributes which are stored as their codable representations. Or maybe something else? In any case, any help you can offer would be greatly appreciated.
Replies
7
Boosts
0
Views
1.5k
Activity
Jun ’26
Using @Environment with TabView
Let me ask the general question first, then explain the context... Each Tab of a TabView defines a separate View hierarchy. (I'm assuming that the root view of each Tab defines its own NavigationStack.) Since an @Environment is supposed to serve data to the child views in its view hierarchy, does this mean that it is possible to define Environments in each tab's root view with the same name (i.e. key) but different values? (I.e., I want a subview to access an environment value for the current view hierarchy without requiring that the subview have any knowledge of which hierarchy it is being called from.) The actual use case has to do with using @Environment in a tabbed application to inject a router in subviews. (Each Tab has its own NavigationStack and its own NavigationPath.) I have an @Observable router class which manages a NavigationPath.. The root view of each Tab in the application has its own instance of that router object (and hence, it's own NavigationPath). I want to inject that router into all of the subviews in each Tab's view hierarchy, so that I can use path-based navigation. My current implementation injects the router throughout the view hierarchies via constructor injection. This works, but is a real pain and includes a bunch of duplicate code. I would like to use @Environment injection instead, but this can only work if @Environment stores its EnvironmentValues on a per view-hierarchy (rather than a per-application) basis. So, can this approach work? what experience can you share concerting router-based navigation in a TabView-based app? Thanks.
Replies
2
Boosts
0
Views
383
Activity
Jan ’26
MacCatalyst and the User's Documents Folder
I have a SwiftUI-based universal app which creates a file that it stores in documentsDirectory. On iOS/iPadOS, this file is stored in the application's Documents directory and is accessible via the Files app. On MacCatalyst, this operation does the same thing — it creates the file and stores it in ~/Library/Containers/<app directory>/Data/Documents. However what I want is for the document to be stored in ~/Documents, so that it is easily accessible to the user. How can I do that? I'd like it to occur without (for example) having to show a SaveFile panel...
Replies
4
Boosts
0
Views
1.2k
Activity
Dec ’25