I am using SwiftData with CloudKit to synchronize data across multiple devices, and I have encountered an issue: occasionally, abnormal sync behavior occurs between two devices (it does not happen 100% of the time—only some users have reported this problem). It seems as if synchronization between the two devices completely stops; no matter what operations are performed on one end, the other end shows no response.
After investigating, I suspect the issue might be caused by both devices simultaneously modifying the same field, which could lead to CloudKit's logic being unable to handle such conflicts and causing the sync to stall. Are there any methods to avoid or resolve this situation?
Of course, I’m not entirely sure if this is the root cause. Has anyone encountered a similar issue?
SwiftData
RSS for tagSwiftData is an all-new framework for managing data within your apps. Models are described using regular Swift code, without the need for custom editors.
Posts under SwiftData tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
I am implementing a premium feature in my app where CloudKit syncing is available only for "Pro" users.
The Workflow:
Free Users: I initialize the ModelContainer with cloudKitDatabase: .none so their data stays local.
Pro Upgrade: When a user purchases a subscription, I restart the container with cloudKitDatabase: .automatic to enable syncing.
The Problem:
If a user starts as "Free" (creates local data) and later upgrades to "Pro", the app crashes immediately upon launch with the following error:
Fatal error: Failed to create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil)
It seems that SwiftData fails to load the existing data once the configuration changes to expect a CloudKit-backed store.
My Question:
Is there a supported way to "toggle" CloudKit on for an existing local dataset without causing this crash? I want the user's existing local data to start syncing once they pay, but currently, it just crashes.
My code:
import Foundation
import SwiftData
public enum DataModelEnum: String {
case task, calendar
public static let container: ModelContainer = {
let isSyncEnabled = UserDefaults.isProUser
let config = ModelConfiguration(
groupContainer: .identifier("group.com.yourcompany.myApp"),
cloudKitDatabase: isSyncEnabled ? .automatic : .none
)
do {
return try ModelContainer(for: TaskModel.self, CalendarModel.self, configurations: config)
} catch {
fatalError("Failed to create ModelContainer: \(error)")
}
}()
}
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
Cloud and Local Storage
SwiftData
Is there a way to view the data saved when using swiftdata? Even after deleting all models, the storage space taken up by the app in Settings is too large.
Hi
Given a simple multiplatform app about Mushrooms, stored in SwiftData, hosted in iCloud using a TextEditor
@Model
final class Champignon: Codable {
var nom: String = ""
../..
@Attribute(.externalStorage)
var attributedStringData: Data = Data()
var attributedString: AttributedString {
get {
do {
return try JSONDecoder().decode(AttributedString.self,
from: attributedStringData)
} catch {
return AttributedString("Failed to decode AttributedString: \(error)")
}
}
set {
do {
self.attributedStringData = try JSONEncoder().encode(newValue)
} catch {
print("Failed to encode AttributedString: \(error)")
}
}
}
../..
Computed attributedString is used in a TextEditor
private var textEditorView: some View {
Section {
TextEditor(text: $model.attributedString)
} header: {
HStack {
Text("TextEditor".localizedUppercase)
.foregroundStyle(.secondary)
Spacer()
}
}
}
Plain Text encode, decode and sync like a charm through iOS and macOS
Use of "FontAttributes" (Bold, Italic, …) works the same
But use of "ForegroundColorAttributes" trigger an error :
Failed to decode AttributedString: dataCorrupted(Swift.DecodingError.Context(codingPath: [_CodingKey(stringValue: "Index 3", intValue: 3), AttributeKey(stringValue: "SwiftUI.ForegroundColor", intValue: nil), CodableBoxCodingKeys(stringValue: "value", intValue: 1)], debugDescription: "Platform color is not available on this platform", underlyingError: nil))
Is there a way to encode/decode attributedString data platform conditionally ?
Or another approach ?
Thanks for advices
I have been working on an app for the past few months, and one issue that I have encountered a few times is an error where quick subsequent deletions cause issues with detached tasks that are triggered from some user actions.
Inside a Task.detached, I am building an isolated model context, querying for LineItems, then iterating over those items. The crash happens when accessing a Transaction property through a relationship.
var byTransactionId: [UUID: [LineItem]] {
return Dictionary(grouping: self) { item in
item.transaction?.id ?? UUID()
}
}
In this case, the transaction has been deleted, but the relationship existed when the fetch occurred, so the transaction value is non-nil. The crash occurs when accessing the id. This is the error.
SwiftData/BackingData.swift:1035: Fatal error: This model instance was invalidated because its backing data could no longer be found the store. PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(backing: SwiftData.PersistentIdentifier.PersistentIdentifierBacking.managedObjectID(0xb43fea2c4bc3b3f5 <x-coredata://A9EFB8E3-CB47-48B2-A7C4-6EEA25D27E2E/Transaction/p1756>)))
I see other posts about this error and am exploring some suggestions, but if anyone has any thoughts, they would be appreciated.
I'm experiencing the following error with my SwiftData container when running a build:
Code=134504 "Cannot use staged migration with an unknown model version."
Code Structure - Summary
I am using a versionedSchema to store multiple models in SwiftData. I started experiencing this issue when adding two new models in the newest Schema version. Starting from the current public version, V4.4.6, there are two migrations.
Migration Summary
The first migration is to V4.4.7. This is a lightweight migration removing one attribute from one of the models. This was tested and worked successfully.
The second migration is to V5.0.0. This is a custom migration adding two new models, and instantiating instances of the two new models based on data from instances of the existing models. In the initial testing of this version, no issues were observed.
Issue and Steps to Reproduce
Reproduction of issue: Starting from a fresh build of the publicly released V4.4.6, I run a new build that contains both Schema Versions (V4.4.7 and V5.0.0), and their associated migration stages. This builds successfully, and the container successfully migrates to V5.0.0. Checking the default.store file, all values appear to migrate and instantiate correctly.
The second step in reproduction of the issue is to simply stop running the build, and then rebuild, without any code changes. This fails to initialize the model container every time afterwards. Going back to the simulator after successive builds are stopped in Xcode, the app launches and accesses/modifies the model container as normal.
Supplementary Issue: I have been putting up with the same, persistent issue in the Xcode Preview Canvas of "Failed to Initialize Model Container" This is a 5 in 6 build issue, where builds will work at random. In the case of previews, I have cleared all data associated with all previews multiple times. The only difference being that the simulator is a 100% failure rate after the initial, successful initialization. I assume this is due to the different build structure of previews. Lastly, of note, the Xcode previews fail at the same line in instantiating the model container as the simulator does. From my research into this issue, people say that the Xcode preview is instantiating from elsewhere. I do have a separate model container set up specifically for canvas previews, but the error does not occur in that container, but rather the app's main container.
Possible Contributing Factors & Tested Facts
iOS: While I have experienced issues with SwiftData and the complier in iOS 26, I can rule that out as the issue here. This has been tested on simulators running iOS 18.6, 26.0.1, and 26.1, all encountering failures to initialize model container. While in iOS 18, subsequent builds after the successful migration did work, I did eventually encounter the same error and crash. In iOS 26.0.1 and 26.1, these errors come immediately on the second build.
Container Initialization for V4.4.6
do {
container = try ModelContainer(
for:
Job.self,
JobTask.self,
Day.self,
Charge.self,
Material.self,
Person.self,
TaskCategory.self,
Service.self,
migrationPlan: JobifyMigrationPlan.self
)
} catch {
fatalError("Failed to Initialize Model Container")
}
Versioned Schema Instance for V4.4.6 (V4.4.7 differs only by versionIdentifier)
static var versionIdentifier = Schema.Version(4, 4, 6)
static var models: [any PersistentModel.Type] {
[Job.self, JobTask.self, Day.self, Charge.self, Material.self, Person.self, TaskCategory.self, Service.self]
}
Container Initialization for V5.0.0
do {
let schema = Schema([Jobify.self,
JobTask.self,
Day.self,
Charge.self,
MaterialItem.self,
Person.self,
TaskCategory.self,
Service.self,
ServiceJob.self,
RecurerRule.self])
container = try ModelContainer(
for: schema, migrationPlan: JobifyMigrationPlan.self
)
} catch {
fatalError("Failed to Initialize Model Container")
}
Versioned Schema Instance for V5.0.0
static var versionIdentifier = Schema.Version(5, 0, 0)
static var models: [any PersistentModel.Type] {
[
JobifySchemaV500.Job.self,
JobifySchemaV500.JobTask.self,
JobifySchemaV500.Day.self,
JobifySchemaV500.Charge.self,
JobifySchemaV500.Material.self,
JobifySchemaV500.Person.self,
JobifySchemaV500.TaskCategory.self,
JobifySchemaV500.Service.self,
JobifySchemaV500.ServiceJob.self,
JobifySchemaV500.RecurerRule.self
]
}
Addressing Differences in Object Names
Type-aliasing: All my model types are type-aliased for simplification in view components. All types are aliased as 'JobifySchemeV446.<#Name#>' in V.4.4.6, and 'JobifySchemaV500.<#Name#>' in V5.0.0
Issues with iOS 26: My type-aliases dating back to iOS 17 overlapped with lower level objects in Swift, including 'Job' and 'Material'. These started to be an issue with initializing the model container when running in iOS 26. The type aliases have been renamed since, however the V4.4.6 build with the old names runs and builds perfectly fine in iOS 26
If there is any other code that may be relevant in determining where this error is occurring, I would be happy to add it. My current best theory is simply that I have mistakenly omitted code relevant to the SwiftData Migration.
I want to support Genmoji input in my SwiftUI TextField or TextEditor, but looking around, it seems there's no SwiftUI only way to do it?
If none, it's kind of disappointing that they're saying SwiftUI is the path forward, but not updating it with support for new technologies.
Going back, does this mean we can only support Genmoji through UITextField and UIViewRepresentable? or there more direct options?
Btw, I'm also using SwiftData for storage.
We have an unreleased SwiftData app for iOS18+. While we were testing I saw reports on the forum about unexpected database migrations for codable arrays on iOS26.1.
I'd like to ask a couple of questions:
1- Does this issue originate from the new Xcode version, or is it specific to iOS 26.1?
2- Is it possible to change our attribute so that users on older iOS versions receive the same model, preventing a migration from being triggered when they upgrade to iOS 26.1?
One of our models looks like this:
struct Point: Codable, Hashable {
let x: Int
let y: Int
}
@Model
class Grid {
private(set) var gridId: String = ""
var points: [Point] = []
var updatedAt: Date = Date()
private(set) var createdAt: Date = Date()
#Index<Grid>([\.gridId])
...
}
I can think of some options like:
// 1
@Attribute(.transformable(by: CustomJsonTransformer.self)) var points: [Point] = []
// 2
@Attribute(.externalStorage) var points: [Point] = []
// 3
var points: Data = Data() // store points as data
However, I'm not sure which one to use.
What would you recommend to handle this, or is there a better strategy you would suggest?
After Xcode 26.1 was updated and installing the OS 26.1 simulators, my app started crashing related to transformable properties. When I checked my schema, I noticed that properties with array collection types are suddenly set with an option transformable with Optional("NSSecureUnarchiveFromData")], even though I do not use any transformable types. I verified the macros, no transformable was specified. This is causing ModelCoders to encode/decode my properties incorrectly.
This is not an issue when I switch back to OS 26.0 simulators.
I've run into a strange issue.
If a sheet loads a view that has a SwiftData @Query, and there is an if statement in the view body, I get the following error when running an iOS targetted SwiftUI app under MacOS 26.1:
Set a .modelContext in view's environment to use Query
While the view actually ends up loading the correct data, before it does, it ends up re-creating the sqlite store (opening as /dev/null).
The strange thing is that this only happens if there is an if statement in the body. The statement need not ever evaluate true, but it causes the issue.
Here's an example. It's based on the default xcode new iOS project w/ SwiftData:
struct ContentView: View {
@State private var isShowingSheet = false
var body: some View {
Button(action: { isShowingSheet.toggle() }) {
Text("Show Sheet")
}
.sheet(isPresented: $isShowingSheet, onDismiss: didDismiss) {
VStack {
ContentSheetView()
}
}
}
func didDismiss() { }
}
struct ContentSheetView: View {
@Environment(\.modelContext) private var modelContext
@Query public var items: [Item]
@State var fault: Bool = false
var body: some View {
VStack {
if fault { Text("Fault!") }
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
List {
ForEach(items) { item in
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
}
}
It requires some data to be added to trigger, but after adding it and dismissing the sheet, opening up the sheet with trigger the Set a .modelContext in view's environment to use Query. Flipping on -com.apple.CoreData.SQLDebug 1 will show it trying to recreate the database.
If you remove the if fault { Text("Fault!") } line, it goes away. It also doesn't appear to happen on iPhones or in the iPhone simulator.
Explicitly passing modelContext to the ContentSheetView like ContentSheetView().modelContext(modelContext) also seems to fix it.
Is this behavior expected?
Hello 👋,
I encounter the "This model instance was invalidated because its backing data could no longer be found the store" crash with SwiftData. Which from what I understood means I try to access a model after it has been removed from the store (makes sense).
I made a quick sample to reproduce/better understand because there some case(s) I can't figure it out.
Let's take a concrete example, we have Home model and a Home can have many Room(s).
// Sample code
@MainActor
let foo = Foo() // A single reference
let database = Database(modelContainer: sharedModelContainer) // A single reference
@MainActor
class Foo {
// Properties to explicilty keep reference of model(s) for the purpose of the POC
var _homes = [Home]()
var _rooms = [Room]()
func fetch() async {
let homes = await database.fetch().map {
sharedModelContainer.mainContext.model(for: $0) as! Home
}
print(ObjectIdentifier(homes[0]), homes[0].rooms?.map(\.id)) // This will crash here or not.
}
// Same version of a delete function with subtle changes.
// Depending on the one you use calling delete then fetch will result in a crash or not.
// Keep a reference to only homes == NO CRASH
func deleteV1() async {
self._homes = await database.fetch().map {
sharedModelContainer.mainContext.model(for: $0) as! Home
}
await database.delete()
}
// Keep a reference to only rooms == NO CRASH
func deleteV2() async {
self._rooms = await database.fetch().map {
sharedModelContainer.mainContext.model(for: $0) as! Home
}[0].rooms ?? []
await database.delete()
}
// Keep a reference to homes & rooms == CRASH 💥
func deleteV3() async {
self._homes = await database.fetch().map {
sharedModelContainer.mainContext.model(for: $0) as! Home
}
self._rooms = _homes[0].rooms ?? []
// or even only retain reference to rooms that have NOT been deleted 🤔 like here "id: 2" make it crash
// self._rooms = _homes[0].rooms?.filter { r in r.id == "2" } ?? []
await database.delete()
}
}
Calling deleteV() then fetch() will result in a crash or not depending on the scenario.
I guess I understand deleteV1, deleteV2. In those case an unsaved model is served by the model(for:) API and accessing properties later on will resolve correctly. The doc says: "The identified persistent model, if known to the context; otherwise, an unsaved model with its persistentModelID property set to persistentModelID."
But I'm not sure about deleteV3. It seems the ModelContext is kind of "aware" there is still cyclic reference between my models that are retained in my code so it will serve these instances instead when calling model(for:) API ? I see my home still have 4 rooms (instead of 2). So I then try to access rooms that are deleted and it crash. Why of that ? I mean why not returning home with two room like in deleteV1 ?
Because SwiftData heavily rely on CoreData may be I miss a very simple thing here. If someone read this and have a clue for me I would be extremely graceful.
PS:
If someone wants to run it on his machine here's some helpful code:
// Database
let sharedModelContainer: ModelContainer = {
let schema = Schema([
Home.self,
Room.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
debugPrint(modelConfiguration.url.absoluteString.replacing("%20", with: "\\ "))
return try! ModelContainer(for: schema, configurations: [modelConfiguration])
}()
extension Database {
static let shared = Database(modelContainer: sharedModelContainer)
}
@ModelActor
actor Database {
func insert() async {
let r1 = Room(id: "1", name: "R1")
let r2 = Room(id: "2", name: "R2")
let r3 = Room(id: "3", name: "R3")
let r4 = Room(id: "4", name: "R4")
let home = Home(id: "1", name: "My Home")
home.rooms = [r1, r2, r3, r4]
modelContext.insert(home)
try! modelContext.save()
}
func fetch() async -> [PersistentIdentifier] {
try! modelContext.fetchIdentifiers(FetchDescriptor<Home>())
}
@MainActor
func delete() async {
let mainContext = sharedModelContainer.mainContext
try! mainContext.delete(
model: Room.self,
where: #Predicate { r in
r.id == "1" || r.id == "4"
}
)
try! mainContext.save()
// 🤔 Calling fetch here seems to solve crash too, force home relationship to be rebuild correctly ?
// let _ = try! sharedModelContainer.mainContext.fetch(FetchDescriptor<Home>())
}
}
// Models
@Model
class Home: Identifiable {
@Attribute(.unique) public var id: String
var name: String
@Relationship(deleteRule: .cascade, inverse: \Room.home)
var rooms: [Room]?
init(id: String, name: String, rooms: [Room]? = nil) {
self.id = id
self.name = name
self.rooms = rooms
}
}
@Model
class Room: Identifiable {
@Attribute(.unique) public var id: String
var name: String
var home: Home?
init(id: String, name: String, home: Home? = nil) {
self.id = id
self.name = name
self.home = home
}
}
Updated the phone to iOS 26.1 and now the app is not working anymore, even previously approved version published on App Store which works perfectly on iOS 26.0.1, and iOS 18+.
I deleted the app from the phone and installed fresh from App Store, still the same.
Logic is that on start app copies previously prepared SwiftData store file (using the same models) from app bundle to Documents directory and uses it.
Currently app just hungs with loader spinner spinning as it can t connect to the store.
Getting this error in console when running from Xcode on real device with iOS 26.1 installed:
CoreData: error:
CoreData: error: Store failed to load. <NSPersistentStoreDescription: 0x10c599e90> (type: SQLite, url: file:///var/mobile/Containers/Data/Application/DA32188D-8887-48F7-B828-1F676C8FBEF8/Documents/default.store)
with error = Error Domain=NSCocoaErrorDomain Code=134140
"Persistent store migration failed, missing mapping model."
UserInfo={sourceModel=(<NSManagedObjectModel: 0x10c503ac0>) isEditable 0,
entities { /// there goes some long models description
addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134140)
Any help or workaround will be greatly appreciated.
Apple WTF? What did you do to all my Apps? none of them work in iOS26.1 (all worked in 26.0).
XCode simply says:
CoreData: error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134140) *
SwiftData is supposed to do all these automatically 🤷🏻
Hi all...
The app I'm building is not really a beginner level test app, it's intended to be published so I want everything to be done properly while I'm both learning and building the app. I'm new to swift ecosystem but well experienced with python and JS ecosystems.
These two models are causing my app to crash
@Model
final class CustomerModel {
var id: String = UUID().uuidString
var name: String = ""
var email: String = ""
var phone: String = ""
var address: String = ""
var city: String = ""
var postalCode: String = ""
var country: String = ""
@Relationship(deleteRule: .nullify)
var orders: [OrderModel]?
@Relationship(deleteRule: .nullify)
var invoices: [InvoiceModel]?
init() {}
}
@Model
final class OrderModel {
var id: String = UUID().uuidString
var total: Double = 0
var status: String = "processing"
var tracking_id: String = ""
var order_date: Date = Date.now
var updated: Date = Date.now
var delivery_date: Date?
var active: Bool = true
var createdAt: Date = Date.now
var items: [OrderItem]?
@Relationship(deleteRule: .nullify)
var invoice: InvoiceModel?
@Relationship(deleteRule: .nullify)
var customer: CustomerModel?
init() {}
}
both referenced in this model:
@Model
final class InvoiceModel{
var id: String = UUID().uuidString
var status: String = "Pending"
var comment: String = ""
var dueDate: Date = Date.now
var createdAt: Date = Date.now
var updated: Date = Date.now
var amount: Double = 0.0
var paymentTerms: String = "Once"
var paymentMethod: String = ""
var paymentDates: [Date] = []
var numOfPayments: Int = 1
@Relationship(deleteRule: .nullify, inverse: \OrderModel.invoice)
var order: OrderModel?
@Relationship(deleteRule: .nullify)
var customer: CustomerModel?
init() {}
}
This is my modelContainer in my index structure:
@main
struct Aje: App {
var appContainer: ModelContainer = {
let schema = Schema([UserModel.self, TaskModel.self, SubtaskModel.self, InventoryModel.self, SupplierModel.self])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false, allowsSave: true, groupContainer: .automatic, cloudKitDatabase: .automatic)
do{
return try ModelContainer(for: schema, configurations: [config])
}catch{
fatalError("An error has occured: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(appContainer)
}
}
This works fine but the below after adding the problematic models crashes the app unless CloudKit is disabled
@main
struct Aje: App {
var appContainer: ModelContainer = {
let schema = Schema([UserModel.self, TaskModel.self, SubtaskModel.self, InventoryModel.self, SupplierModel.self, InvoiceModel.self, OrderModel.self, CustomerModel.self])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false, allowsSave: true, groupContainer: .automatic, cloudKitDatabase: .automatic)
do{
return try ModelContainer(for: schema, configurations: [config])
}catch{
fatalError("An error has occured: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(appContainer)
}
}
Topic:
Developer Tools & Services
SubTopic:
Xcode Cloud
Tags:
Swift Packages
CloudKit
SwiftUI
SwiftData
If an app is using top-level models, meaning they exist outside the VersionedSchema enum, is it safe to keep them outside of the VersionedSchema enum and use a migration plan for simple migrations. Moving the models within the VersionedSchema enum I believe would change the identity of the models and result in data being lost, although correct me if I'm wrong in that statement.
The need presently is just to add another variable to the model and then set that variable within the init function:
var updateId = UUID()
The app is presently in TestFlight although I'd like to preserve data for users that are currently using the app.
The data within SwiftData is synchronized with CloudKit and so I'd also like to avoid any impact to synchronization.
Any thoughts on this would be greatly appreciated.
Hi there! I'm making an app that stores data for the user's profile in SwiftData. I was originally going to use UserDefaults but I thought SwiftData could save Images natively but this is not true so I really could switch back to UserDefaults and save images as Data but I'd like to try to get this to work first. So essentially I have textfields and I save the values of them through a class allProfileData. Here's the code for that:
import SwiftData
import SwiftUI
@Model
class allProfileData {
var profileImageData: Data?
var email: String
var bio: String
var username: String
var profileImage: Image {
if let data = profileImageData,
let uiImage = UIImage(data: data) {
return Image(uiImage: uiImage)
} else {
return Image("DefaultProfile")
}
}
init(email:String, profileImageData: Data?, bio: String, username:String) {
self.profileImageData = profileImageData
self.email = email
self.bio = bio
self.username = username
}
}
To save this I create a new class (I think, I'm new) and save it through ModelContext
import SwiftUI
import SwiftData
struct CreateAccountView: View {
@Query var profiledata: [allProfileData]
@Environment(\.modelContext) private var modelContext
let newData = allProfileData(email: "", profileImageData: nil, bio: "", username: "")
var body: some View {
Button("Button") {
newData.email = email
modelContext.insert(newData)
try? modelContext.save()
print(newData.email)
}
}
}
To fetch the data, I originally thought that @Query would fetch that data but I saw that it fetches it asynchronously so I attempted to manually fetch it, but they both fetched nothing
import SwiftData
import SwiftUI
@Query var profiledata: [allProfileData]
@Environment(\.modelContext) private var modelContext
let fetchRequest = FetchDescriptor<allProfileData>()
let fetchedData = try? modelContext.fetch(fetchRequest)
print("Fetched count: \(fetchedData?.count ?? 0)")
if let imageData = profiledata.first?.profileImageData,
let uiImage = UIImage(data: imageData) {
profileImage = Image(uiImage: uiImage)
} else {
profileImage = Image("DefaultProfile")
}
No errors. Thanks in advance
I have SwiftData models containing arrays of Codable structs that worked fine before adding CloudKit capability. I believe they are the reason I started seeing errors after enabling CloudKit.
Example model:
@Model
final class ProtocolMedication {
var times: [SchedulingTime] = [] // SchedulingTime is Codable
// other properties...
}
After enabling CloudKit, I get this error logged to the console:
'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
CloudKit Console shows this times data as "plain text" instead of "bplist" format.
Other struct/enum properties display correctly (I think) as "bplist" in CloudKit Console.
The local SwiftData storage handled these arrays fine - this issue only appeared with CloudKit integration.
What's the recommended approach for storing arrays of Codable structs in SwiftData models that sync with CloudKit?
When I used to do Migrations, I always used ETL and then push to a dev system to review/test before going production.
The migration support is SwiftData is fine for a little tweak.
I might as well just just use new schema and context and write the custom code than use the SwiftData migration support.
Hello,
In our app, we’ve modeled our schema using inheritance introduced in iOS 26.0, and we’re implementing SwiftData History to re-fetch models only when necessary.
@Model public class Transaction {
@Attribute(.preserveValueOnDeletion)
public var date: Date = Date()
public var amount: Double = 0
public var memo: String?
}
@Model public final class Spending: Transaction {
public var installmentIndex: Int = 1
public var installment: Int = 1
public var installmentID: UUID?
}
If data has been deleted from database, we need to check a date property to determine whether to re-fetch datas.
To do this, we added the preserveValueOnDeletion attribute to date property so we could retrieve it from the History tombstone value.
However, after adding this attribute, a crash occurs. There is a console log
Could not cast value of type 'Swift.ReferenceWritableKeyPath<Shared.ModelSchemaV5.Transaction, Foundation.Date>' (0x106bf8328) to 'Swift.PartialKeyPath<Shared.ModelSchemaV5.Spending>' (0x1094f21d8).
and error log attached
StrictMoneyChecking-2025-11-07-105108.txt
I also tried this in the recent SampleTrip app, and fetching all history after a deletion causes the same crash.
Is this issue currently being worked on or under investigation?
Hi everyone,
I'm looking for the correct architectural guidance for my SwiftData implementation.
In my Swift project, I have dedicated async functions for adding, editing, and deleting each of my four models. I created these functions specifically to run certain logic whenever these operations occur. Since these functions are asynchronous, I call them from the UI (e.g., from a button press) by wrapping them in a Task.
I've gone through three different approaches and am now stuck.
Approach 1: @MainActor Functions
Initially, my functions were marked with @MainActor and worked on the main ModelContext. This worked perfectly until I added support for App Intents and Widgets, which caused the app to crash with data race errors.
Approach 2: Passing ModelContext as a Parameter
To solve the crashes, I decided to have each function receive a ModelContext as a parameter. My SwiftUI views passed the main context (which they get from @Environment(\.modelContext)), while the App Intents and Widgets created and passed in their own private context. However, this approach still caused the app to crash sometimes due to data race errors, especially during actions triggered from the main UI.
Approach 3: Creating a New Context in Each Function
I moved to a third approach where each function creates its own ModelContext to work on. This has successfully stopped all crashes. However, now the UI actions don't always react or update. For example, when an object is added, deleted, or edited, the change isn't reflected in the UI. I suspect this is because the main context (driving the UI) hasn't been updated yet, or because the async function hasn't finished its work.
My Question
I'm not sure what to do or what the correct logic should be. How should I structure my data operations to support the main UI, Widgets, and App Intents without causing crashes or UI update failures?
Here is the relevant code using my third (and current) approach. I've shortened the helper functions for brevity.
// MARK: - SwiftData Operations
extension DatabaseManager {
/// Creates a new assignment and saves it to the database.
public func createAssignment(
name: String, deadline: Date, notes: AttributedString,
forCourseID courseID: UUID, /*...other params...*/
) async throws -> AssignmentModel {
do {
let context = ModelContext(container)
guard let course = findCourse(byID: courseID, in: context) else {
throw DatabaseManagerError.itemNotFound
}
let newAssignment = AssignmentModel(
name: name, deadline: deadline, notes: notes, course: course, /*...other properties...*/
)
context.insert(newAssignment)
try context.save()
// Schedule notifications and add to calendar
_ = try? await scheduleReminder(for: newAssignment)
newAssignment.calendarEventIDs = await CalendarManager.shared.addEventToCalendar(for: newAssignment)
try context.save()
await MainActor.run {
WidgetCenter.shared.reloadTimelines(ofKind: "AppWidget")
}
return newAssignment
} catch {
throw DatabaseManagerError.saveFailed
}
}
/// Finds a specific course by its ID in a given context.
public func findCourse(byID id: UUID, in context: ModelContext) -> CourseModel? {
let predicate = #Predicate<CourseModel> { $0.id == id }
let fetchDescriptor = FetchDescriptor<CourseModel>(predicate: predicate)
return try? context.fetch(fetchDescriptor).first
}
}
// MARK: - Helper Functions (Implementations omitted for brevity)
/// Schedules a local user notification for an event.
func scheduleReminder(for assignment: AssignmentModel) async throws -> String {
// ... Full implementation to create and schedule a UNNotificationRequest
return UUID().uuidString
}
/// Creates a new event in the user's selected calendars.
extension CalendarManager {
func addEventToCalendar(for assignment: AssignmentModel) async -> [String] {
// ... Full implementation to create and save an EKEvent
return [UUID().uuidString]
}
}
Thank you for your help.