Some users of my app are reporting total loss of data while using the app.
This is happening specifically when they enable iCloud sync.
I am doing following
private func setupContainer(enableICloud: Bool) {
    container = NSPersistentCloudKitContainer(name: "")
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    guard let description: NSPersistentStoreDescription = container.persistentStoreDescriptions.first else {
        fatalError()
    }
    description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    if enableICloud == false {
        description.cloudKitContainerOptions = nil
    }
    container.loadPersistentStores { description, error in
        if let error {
            // Handle error
        }
    }
}
When user clicks on Toggle to enable/disable iCloud sync I just set the description.cloudKitContainerOptions to nil and then user is asked to restart the app.
Apart from that I periodically run the clear history
func deleteTransactionHistory() {
    let sevenDaysAgo = Calendar.current.date(byAdding: .day, value: -7, to: Date())!
    let purgeHistoryRequest = NSPersistentHistoryChangeRequest.deleteHistory(before: sevenDaysAgo)
    let backgroundContext = container.newBackgroundContext()
    backgroundContext.performAndWait {
        try! backgroundContext.execute(purgeHistoryRequest)
    }
}
                    
                  
                iCloud & Data
RSS for tagLearn how to integrate your app with iCloud and data frameworks for effective data storage
  
    
    Selecting any option will automatically load the page
  
  
  
  
    
  
  
            Post
Replies
Boosts
Views
Activity
                    
                      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.
                    
                  
                
                    
                      In the future, is there any plans to have AppMigrationKit for macOS-Windows cross transfers (or Linux, ChromeOS, HarmonyOS NEXT, etc)? Additionally, will the migration framework remain just iOS <-> Android or will it extend to Windows tablets, ChromeOS Tablets, HarmonyOS NEXT, KaiOS, Series 30+, Linux mobile, etc.
                    
                  
                
              
                
              
              
                
                Topic:
                  
	
		App & System Services
  	
                
                
                SubTopic:
                  
                    
	
		iCloud & Data
		
  	
                  
                
              
              
              
  
  
    
    
  
  
              
                
                
              
            
          
                    
                      I'm experiencing a critical issue with SwiftData custom migrations where objects created during migration appear to be inserted successfully but aren't persisted or found by queries after migration completes. The migration logs show objects being created, but subsequent queries return zero results.
I'm migrating from schema version V2 to V2_5, which involves:
Renaming Person class to GroupData
Keeping the same data structure but changing the class name while keeping the old class.
Using a custom migration stage to copy data from old to new schema
Below is an extract of my two schema and migration plan:
Environment:
Xcode 16.0,
iOS 18.0,
Swift 6.0
SchemaV2
enum LinkMapV2: VersionedSchema {
    static let versionIdentifier: Schema.Version = .init(2, 0, 0)
    static var models: [any PersistentModel.Type] {
        [AnnotationData.self, Person.self, History.self]
    }
    
    @Model
    final class Person {
        @Attribute(.unique) var id: UUID
        var name: String
        var photo: String
        var requirement: String
        var statue: Bool
        var annotationId: UUID?
        var number: Int = 0
        
        init(id: UUID = UUID(), name: String = "", photo: String = "", requirement: String = "", status: Bool = false, annotationId: UUID? = nil, number: Int = 0) {
            self.id = id
            self.name = name
            self.photo = photo
            self.requirement = requirement
            self.statue = status
            self.annotationId = annotationId
            self.number = number
        }
    }
}
Schema V2_5
    static let versionIdentifier: Schema.Version = .init(2, 5, 0)
    static var models: [any PersistentModel.Type] {
        [AnnotationData.self, Person.self, GroupData.self, History.self]
    }
    
    // Keep the old Person model for migration
    @Model
    final class Person {
        @Attribute(.unique) var id: UUID
        var name: String
        var photo: String
        var requirement: String
        var statue: Bool
        var annotationId: UUID?
        var number: Int = 0
        
        init(id: UUID = UUID(), name: String = "", photo: String = "", requirement: String = "", status: Bool = false, annotationId: UUID? = nil, number: Int = 0) {
            self.id = id
            self.name = name
            self.photo = photo
            self.requirement = requirement
            self.statue = status
            self.annotationId = annotationId
            self.number = number
        }
    }
    
    // Add the new GroupData model that mirrors Person
    @Model
    final class GroupData {
        @Attribute(.unique) var id: UUID
        var name: String
        var photo: String
        var requirement: String
        var status: Bool
        var annotationId: UUID?
        var number: Int = 0
        
        init(id: UUID = UUID(), name: String = "", photo: String = "", requirement: String = "", status: Bool = false, annotationId: UUID? = nil, number: Int = 0) {
            self.id = id
            self.name = name
            self.photo = photo
            self.requirement = requirement
            self.status = status
            self.annotationId = annotationId
            self.number = number
        }
    }
}
Migration Plan
    static let migrationV2toV2_5 = MigrationStage.custom(
        fromVersion: LinkMapV2.self,
        toVersion: LinkMapV2_5.self,
        willMigrate: { context in
            do {
                let persons = try context.fetch(FetchDescriptor<LinkMapV2.Person>())
                
                print("=== MIGRATION STARTED ===")
                print("Found \(persons.count) Person objects to migrate")
                
                guard !persons.isEmpty else {
                    print("No Person data requires migration")
                    return
                }
                
                for person in persons {
                    print("Migrating Person: '\(person.name)' with ID: \(person.id)")
                    
                    let newGroup = LinkMapV2_5.GroupData(
                        id: person.id, // Keep the same ID
                        name: person.name,
                        photo: person.photo,
                        requirement: person.requirement,
                        status: person.statue,
                        annotationId: person.annotationId,
                        number: person.number
                    )
                    
                    context.insert(newGroup)
                    print("Inserted new GroupData: '\(newGroup.name)'")
                    
                    // Don't delete the old Person yet to avoid issues
                    // context.delete(person)
                }
                
                try context.save()
                print("=== MIGRATION COMPLETED ===")
                print("Successfully migrated \(persons.count) Person objects to GroupData")
                
            } catch {
                print("=== MIGRATION ERROR ===")
                print("Migration failed with error: \(error)")
            }
        },
        didMigrate: { context in
            do {
                // Verify migration in didMigrate phase
                let groups = try context.fetch(FetchDescriptor<LinkMapV2_5.GroupData>())
                let oldPersons = try context.fetch(FetchDescriptor<LinkMapV2_5.Person>())
                
                print("=== MIGRATION VERIFICATION ===")
                print("New GroupData count: \(groups.count)")
                print("Remaining Person count: \(oldPersons.count)")
                
                // Now delete the old Person objects
                for person in oldPersons {
                    context.delete(person)
                }
                
                if !oldPersons.isEmpty {
                    try context.save()
                    print("Cleaned up \(oldPersons.count) old Person objects")
                }
                
                // Print all migrated groups for debugging
                for group in groups {
                    print("Migrated Group: '\(group.name)', Status: \(group.status), Number: \(group.number)")
                }
                
            } catch {
                print("Migration verification error: \(error)")
            }
        }
    )
And I've attached console output below:
Console Output
                    
                  
                
                    
                      Description:
I'm experiencing a critical issue with SwiftData custom migrations where objects created during migration appear to be inserted successfully but aren't persisted or found by queries after migration completes. The migration logs show objects being created, but subsequent queries return zero results.
Problem Details:
I'm migrating from schema version V2 to V3, which involves:
Renaming Person class to GroupData
Keeping the same data structure but changing the class name
Using a custom migration stage to copy data from old to new schema
Migration Code:
swift
static let migrationV2toV3 = MigrationStage.custom(
fromVersion: LinkMapV2.self,
toVersion: LinkMapV3.self,
willMigrate: { context in
do {
let persons = try context.fetch(FetchDescriptor<LinkMapV2.Person>())
print("Found (persons.count) Person objects to migrate") // ✅ Shows 11 objects
        for person in persons {
            let newGroup = LinkMapV3.GroupData(
                id: person.id, // Same UUID
                name: person.name,
                // ... other properties
            )
            context.insert(newGroup)
            print("Inserted GroupData: '\(newGroup.name)'") // ✅ Confirms insertion
        }
        
        try context.save() // ✅ No error thrown
        print("Successfully migrated \(persons.count) objects") // ✅ Confirms save
        
    } catch {
        print("Migration error: \(error)")
    }
},
didMigrate: { context in
    do {
        let groups = try context.fetch(FetchDescriptor<LinkMapV3.GroupData>())
        print("Final GroupData count: \(groups.count)") // ❌ Shows 0 objects!
    } catch {
        print("Verification error: \(error)")
    }
}
)
Console Output:
text
=== MIGRATION STARTED ===
Found 11 Person objects to migrate
Migrating Person: 'Riverside of pipewall' with ID: 7A08C633-4467-4F52-AF0B-579545BA88D0
Inserted new GroupData: 'Riverside of pipewall'
... (all 11 objects processed) ...
=== MIGRATION COMPLETED ===
Successfully migrated 11 Person objects to GroupData
=== MIGRATION VERIFICATION ===
New GroupData count: 0  // ❌ PROBLEM: No objects found!
What I've Tried:
Multiple context approaches:
Using the provided migration context
Creating a new background context with ModelContext(context.container)
Using context.performAndWait for thread safety
Different save strategies:
Calling try context.save() after insertions
Letting SwiftData handle saving automatically
Multiple save calls at different points
Verification methods:
Checking in didMigrate closure
Checking in app's ContentView after migration completes
Using both @Query and manual FetchDescriptor
Schema variations:
Direct V2→V3 migration
Intermediate V2.5 schema with both classes
Lightweight migration with @Attribute(originalName:)
Current Behavior:
Migration runs without errors
Objects appear to be inserted successfully
context.save() completes without throwing errors
But queries in didMigrate and post-migration return empty results
The objects seem to exist in a temporary state that doesn't persist
Expected Behavior:
Objects created during migration should be persisted and queryable
Post-migration queries should return the migrated objects
Data should be available in the main app after migration completes
Environment:
Xcode 16.0+
iOS 18.0+
SwiftData
Swift 6.0+
Key Questions:
Is there a specific way migration contexts should be handled for data to persist?
Are there known issues with object persistence in custom migrations?
Should we be using a different approach for class renaming migrations?
Is there a way to verify that objects are actually being written to the persistent store?
The migration appears to work perfectly until the verification step, where all created objects seem to vanish. Any guidance would be greatly appreciated!
Additional Context from my investigation:
I've noticed these warning messages during migration that might be relevant:
text
SwiftData.ModelContext: Unbinding from the main queue. This context was instantiated on the main queue but is being used off it.
error: Persistent History (76) has to be truncated due to the following entities being removed: (Person)
This suggests there might be threading or context lifecycle issues affecting persistence.
Let me know if you need any additional information about my setup or migration configuration!
                    
                  
                
                    
                      I'm testing my app before releasing to testers, and my app (both macOS and iOS) is crashing when I perform one operation, but only in the production build.
I have data that loads from a remote source, and can be periodically updated. There is an option to delete all of that data from the iCloud data store, unless the user has modified a record. Each table has a flag to indicate that (userEdited). Here's the function that is crashing:
func deleteCommonData<T:PersistentModel & SDBuddyModel>(_ type: T.Type) throws {
    try modelContext.delete(model: T.self, where: #Predicate<T> { !$0.userEdited })
}
Here's one of the calls that results in a crash:
try modelManager.deleteCommonData(Link.self)
Here's the error from iOS Console:
SwiftData/DataUtilities.swift:85: Fatal error: Couldn't find \Link.<computed 0x0000000104b9d208 (Bool)> on Link with fields [SwiftData.Schema.PropertyMetadata(name: "id", keypath: \Link.<computed 0x0000000104b09b44 (String)>, defaultValue: Optional("54EC6602-CA7C-4EC7-AC06-16E7F2E22DE7"), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "name", keypath: \Link.<computed 0x0000000104b09b84 (String)>, defaultValue: Optional(""), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "url", keypath: \Link.<computed 0x0000000104b09bc4 (String)>, defaultValue: Optional(""), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "desc", keypath: \Link.<computed 0x0000000104b09c04 (String)>, defaultValue: Optional(""), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "userEdited", keypath: \Link.<computed 0x0000000104b09664 (Bool)>, defaultValue: Optional(false), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "modified", keypath: \Link.<computed 0x0000000104b09c44 (Date)>, defaultVal<…>
Here's a fragment of the crash log:
Exception Type:    EXC_BREAKPOINT (SIGTRAP)
Exception Codes:   0x0000000000000001, 0x000000019373222c
Termination Reason:  Namespace SIGNAL, Code 5, Trace/BPT trap: 5
Terminating Process: exc handler [80543]
Thread 0 Crashed:
0   libswiftCore.dylib            	       0x19373222c _assertionFailure(_:_:file:line:flags:) + 176
1   SwiftData                     	       0x22a222160 0x22a1ad000 + 479584
2   SwiftData                     	       0x22a2709c0 0x22a1ad000 + 801216
3   SwiftData                     	       0x22a221b08 0x22a1ad000 + 477960
4   SwiftData                     	       0x22a27b0ec 0x22a1ad000 + 844012
5   SwiftData                     	       0x22a27b084 0x22a1ad000 + 843908
6   SwiftData                     	       0x22a28182c 0x22a1ad000 + 870444
7   SwiftData                     	       0x22a2809e8 0x22a1ad000 + 866792
8   SwiftData                     	       0x22a285204 0x22a1ad000 + 885252
9   SwiftData                     	       0x22a281c7c 0x22a1ad000 + 871548
10  SwiftData                     	       0x22a27cf6c 0x22a1ad000 + 851820
11  SwiftData                     	       0x22a27cc48 0x22a1ad000 + 851016
12  SwiftData                     	       0x22a27a6b0 0x22a1ad000 + 841392
13  SwiftData                     	       0x22a285b2c 0x22a1ad000 + 887596
14  SwiftData                     	       0x22a285a10 0x22a1ad000 + 887312
15  SwiftData                     	       0x22a285bcc 0x22a1ad000 + 887756
16  SwiftData                     	       0x22a27cf6c 0x22a1ad000 + 851820
17  SwiftData                     	       0x22a27cc48 0x22a1ad000 + 851016
18  SwiftData                     	       0x22a27a6b0 0x22a1ad000 + 841392
19  SwiftData                     	       0x22a27c0d8 0x22a1ad000 + 848088
20  SwiftData                     	       0x22a27a654 0x22a1ad000 + 841300
21  SwiftData                     	       0x22a1be548 0x22a1ad000 + 70984
22  SwiftData                     	       0x22a1cfd64 0x22a1ad000 + 142692
23  SwiftData                     	       0x22a1b9618 0x22a1ad000 + 50712
24  SwiftData                     	       0x22a1d2e8c 0x22a1ad000 + 155276
25  CoreData                      	       0x187fbb568 thunk for @callee_guaranteed () -> (@out A, @error @owned Error) + 28
26  CoreData                      	       0x187fc2300 partial apply for thunk for @callee_guaranteed () -> (@out A, @error @owned Error) + 24
27  CoreData                      	       0x187fc19c4 closure #1 in closure #1 in NSManagedObjectContext._rethrowsHelper_performAndWait<A>(fn:execute:rescue:) + 192
28  CoreData                      	       0x187fbbda8 thunk for @callee_guaranteed @Sendable () -> () + 28
29  CoreData                      	       0x187fbbdd0 thunk for @escaping @callee_guaranteed @Sendable () -> () + 28
30  CoreData                      	       0x187f663fc developerSubmittedBlockToNSManagedObjectContextPerform + 252
31  libdispatch.dylib             	       0x180336ac4 _dispatch_client_callout + 16
32  libdispatch.dylib             	       0x18032c940 _dispatch_lane_barrier_sync_invoke_and_complete + 56
33  CoreData                      	       0x187fd7290 -[NSManagedObjectContext performBlockAndWait:] + 364
34  CoreData                      	       0x187fc1fb8 NSManagedObjectContext.performAndWait<A>(_:) + 544
35  SwiftData                     	       0x22a1b877c 0x22a1ad000 + 46972
36  SwiftData                     	       0x22a1be2a8 0x22a1ad000 + 70312
37  SwiftData                     	       0x22a1c0e34 0x22a1ad000 + 81460
38  SwiftData                     	       0x22a23ea94 0x22a1ad000 + 596628
39  SwiftData                     	       0x22a256828 0x22a1ad000 + 694312
40  Sourdough Buddy               	       0x104e5dc98 specialized ModelManager.deleteCommonData<A>(_:) + 144 (ModelManager.swift:128) [inlined]
41  Sourdough Buddy               	       0x104e5dc98 closure #1 in SettingsView.clearStarterData.getter + 876 (SettingsView.swift:243)
It works if I do the following instead:
try modelContext.delete(model: Link.self, where: #Predicate { !$0.userEdited })
Why would the func call work in development, but crash in production? And why does doing the more verbose way work instead?
I think this is a bug.
Thanks
                    
                  
                
                    
                      I'm using Swift Data for an app that requires iOS 18.
All of my models conform to a protocol that guarantees they have a 'serverID' String variable.
I wrote a function that would allow me to pass in a serverID String and have it fetch the model object that matched. Because I am lazy and don't like writing the same functions over and over, I used a Self reference so that all of my conforming models get this static function.
Imagine my model is called "WhatsNew". Here's some code defining the protocol and the fetching function.
protocol RemotelyFetchable: PersistentModel {
    var serverID: String { get }
}
extension WhatsNew: RemotelyFetchable {}
extension RemotelyFetchable {
    static func fetchOne(withServerID identifier: String, inContext modelContext: ModelContext) -> Self? {
        var fetchDescriptor = FetchDescriptor<Self>()
        fetchDescriptor.predicate = #Predicate<Self> { $0.serverID == identifier }
        do {
            let allModels = try modelContext.fetch(fetchDescriptor)
            
            return allModels.first
        } catch {
            return nil
        }
    }
}
Worked great! Or so I thought...
I built this and happily ran a debug build in the Simulator and on devices for months while developing the initial version but when I went to go do a release build for TestFlight, that build reliably crashed on every device with a message like this:
SwiftData/DataUtilities.swift:65: Fatal error: Couldn't find \WhatsNew. on WhatsNew with fields [SwiftData.Schema.PropertyMetadata(name: "serverID", keypath: \WhatsNew., defaultValue: nil, metadata: Optional(Attribute - name: , options: [unique], valueType: Any, defaultValue: nil, hashModifier: nil)), SwiftData.Schema.PropertyMetadata(name: "title", keypath: \WhatsNew., defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "bulletPoints", keypath: \WhatsNew.)>, defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "dateDescription", keypath: \WhatsNew., defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "readAt", keypath: \WhatsNew.)>, defaultValue: nil, metadata: nil)]
It seems (cannot confirm) that something in the release build optimization process is stripping out some metadata / something about these models that makes this predicate crash.
Tested on iOS 18.0 and 18.1 beta.
How can I resolve this? I have two dozen types that conform to this protocol. I could manually specialize this function for every type myself but... ugh.
                    
                  
                
                    
                      i want to save data like images, text,amd mapviews with swiftui. It is only saved but if you delete the app of buy a new iPhone everything is deleted, how can I make if that the information saved on my app is saved even after I update the app, delete the app, or put the app in another iPhone with SwiftUI? i have watched youtube videos and im still confused,please help.
                    
                  
                
                    
                      The CloudKit Console includes a Unique Users table in the Usage section.
The numbers here are lower than what I would expect. Does this only track a certain percentage of users, e.g. users have opted in to share analytics with developers?
                    
                  
                
                    
                      I'm trying to handle the serverRecordChanged return code you get in CKError when you have a conflict and your using the savePolicy of ifServerRecordUnchanged.
According to the CKError.Code.serverRecordChanged documentation, I should be receiving all three records that I need to do a 3-way merge. The problem is that the ancestorRecord (CKRecordChangedErrorAncestorRecordKey can also be used to look it up in the userInfo) doesn't actually contain a record. It only contains the record metadata.
Is there something I need to be doing to get the full ancestorRecord in the CKError?
If not is it possible to query iCloud for the ancestorRecord? Given that iCloud has the change history (as I understand it), then it is theoretically possible. I just don't know how to do it if it is possible.
Are 3-way merges even possible? The design of the serverRecordChanged looks like that is the intent, but I can't see how to do it with the data that CloudKit is providing.
                    
                  
                
                    
                      Hello,
From the documentation linked below, the limitations for Background Assets are the following:
Size Limit: 200 GB
Asset Pack Count: 100
I'm expecting I will need ~175 Asset Packs and around 500GB of storage.
I understand Background Assets is a new, but is there a process or a potential that these limits will be increased in the future? Or is there a way to request an increase?
I've tried contacting Apple Support as this is more of an Admin issue, however they've directed me here.
Case ID 102725356578
https://developer.apple.com/help/app-store-connect/reference/apple-hosted-asset-pack-size-limits
Thank you,
Tanner
                    
                  
                
                    
                      Hi,
Not sure how to describe my issue best: I am using SwiftData and CloudKit to store my data.
In the past, when I tested my app on different devices, the data would sync between the devices automatically. For whatever reason this has stopped now and the data no longer syncs. No matter what I do, it feels as if all the data is actually stored just locally on each device.
How can I check if the data is actually stored in the cloud and what could be reasons, why its no longer synching between my devices (and yes, I am logged in with the same Apple ID on all devices).
Thanks for any hint!
Max
                    
                  
                
                    
                      When deleting a SwiftData entity, I sometimes encounter the following error in a document based SwiftUI app:
Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<MyEntityClass>
The deletion happens in a SwiftUI View and the code used to retrieve the entity is standard (the ModelContext is injected from the @Environment):
let myEntity = modelContext.model(for: entityIdToDelete)
modelContext.delete(myEntity)
Unfortunately, I haven't yet managed to isolate this any further in order to come up with a reproducible PoC.
Could you give me further information about what this error means?
                    
                  
                
                    
                      I’m building an app that edits files in iCloud and uses an NSFilePresenter to monitor changes.
When a conflict occurs, the system calls presentedItemDidGain(_:).
In that method, I merge the versions by reading the current (canonical) version using NSFileVersion.currentVersionOfItem(at:) and the conflicting ones using NSFileVersion.unresolvedConflictVersionsOfItem(at:).
This generally works, but sometimes, if two devices edit the same file at the same time, each device sees its own local version as the current one. For example:
Device A writes fileVerA (slightly later in real time)
Device B writes fileVerB
On Device A all works fine, currentVersionOfItem returns fileVerA, as expected, and unresolvedConflictVersionsOfItem returns [fileVerB].
But on Device B, currentVersionOfItem returns fileVerB!? And unresolvedConflictVersionsOfItem returns the same, local file [fileVerB], without any hint of the other conflicting version, fileVerA.
Later, the newer version from the Device A arrives on Device B as a normal, non-conflicting update via presentedItemDidChange(_:).
This seems to contradict Apple’s documentation:
“The currentVersionOfItemAtURL: method returns an NSFileVersion object representing what’s referred to as the current file; the current file is chosen by iCloud on some basis as the current “conflict winner” and is the same across all devices.”
Is this expected behavior, or a bug in how iCloud reports file versions?
                    
                  
                
                    
                      Hello Apple Team,
We’re building a CloudKit-enabled Core Data app and would like clarification on the behavior and performance characteristics of Binary Data attributes with “Allows External Storage” enabled when used with NSPersistentCloudKitContainer.
Initially, we tried storing image files manually on disk and only saving the metadata (file URLs, dimensions, etc.) in Core Data. While this approach reduced the size of the Core Data store, it introduced instability after app updates and broke sync between devices. We would prefer to use the official Apple-recommended method and have Core Data manage image storage and CloudKit syncing natively.
Specifically, we’d appreciate guidance on the following:
When a Binary Data attribute is marked as “Allows External Storage”, large image files are stored as separate files on device rather than inline in the SQLite store.
How effective is this mechanism in keeping the Core Data store size small on device?
Are there any recommended size thresholds or known limits for how many externally stored blobs can safely be managed this way?
How are these externally stored files handled during CloudKit sync?
Does each externally stored Binary Data attribute get mirrored to CloudKit as a CKAsset?
Does external storage reduce the sync payload size or network usage, or is the full binary data still uploaded/downloaded as part of the CKAsset?
Are there any bandwidth implications for users syncing via their private CloudKit database, versus developer costs in the public CloudKit database?
Is there any difference in CloudKit or Core Data behavior when a Binary Data attribute is managed this way versus manually storing image URLs and handling the file separately on disk?
Our goal is to store user-generated images efficiently and safely sync them via CloudKit, without incurring excessive local database bloat or CloudKit network overhead.
Any detailed guidance or internal performance considerations would be greatly appreciated.
Thank you,
Paul Barry
Founder & Lead Developer — Boat Buddy / Vessel Buddy iOS App
Archipelago Environmental Solutions Inc.
                    
                  
                
                    
                      I'm running a project with these settings:
Default Actor Isolation: MainActor
Approachable Concurrency: Yes
Strict Concurrency Checking: Complete (this issue does not appear on the other two modes)
I receive a warning for this very simple use case. Can I actually fix anything about this or is this a case of Core Data not being entirely ready for this?
In reference to this, there was a workaround listed in the release notes of iOS 26 beta 5 (https://forums.swift.org/t/defaultisolation-mainactor-and-core-data-background-tasks/80569/22). Does this still apply as the only fix for this?
This is a simplified sample meant to run on a background context. The issue obviously goes away if this function would just run on the MainActor, then I can remove the perform block entirely.
class DataHandler {    
    func createItem() async {
        let context = ...
        
        await context.perform {
            let newGame = Item(context: context)
            
            /// Main actor-isolated property 'timestamp' can not be mutated from a Sendable closure
            newGame.timestamp = Date.now
            
            // ...
        }
    }
}
The complete use case would be more like this:
nonisolated
struct DataHandler {
    @concurrent
    func saveItem() async throws {
        let context = await PersistenceController.shared.container.newBackgroundContext()
                
        try await context.perform {
            let newGame = Item(context: context)
            
            newGame.timestamp = Date.now
        
            try context.save()
        }
    }
}
                    
                  
                
                    
                      Hello Apple Team,
We are looking at developing an iOS feature on our current development  that stores user-generated images as CKAssets in the public CloudKit database, with access control enforced by our app’s own logic (not CloudKit Sharing as that has a limit of 100 shares per device). Each story or post is a public record, and users only see content based on buddy relationships handled within the app.
We’d like to confirm that this pattern is consistent with Apple’s best practices for social features. Specifically:
Is it acceptable to store user-uploaded CKAssets in the public CloudKit database, as long as access visibility is enforced by the app?
Are there any performance or quota limitations (e.g., storage, bandwidth, or user sync limits) that apply to CKAssets in the public database when used at scale?
Would CloudKit Sharing be recommended instead, even if we don’t require user-to-user sharing invitations?
For App Review, is this model (public CKAssets + app-enforced access control) compliant with Apple’s data and security expectations?
Are there any caching or bandwidth optimization guidelines for handling image-heavy public CKAsset data in CloudKit?
Thanks again for your time
                    
                  
                
                    
                      Hi everyone,
We’re currently using CKSyncEngine to sync all our locally persisted data across user devices (iOS and macOS) via iCloud.
We’ve noticed something strange and reproducible:
On iOS, when the CKSyncEngine is initialized with manual sync behavior, both manual calls to fetchChanges() and sendChanges() happen nearly instantly (usually within seconds). Automatic syncing is also very fast.
On macOS, when the CKSyncEngine is initialized with manual sync behavior, fetchChanges() and sendChanges() are also fast and responsive.
However, once CKSyncEngine is initialized with automatic syncing enabled on macOS:
sendChanges() still appears to transmit changes immediately.
But automatic fetching becomes significantly slower — often taking minutes to pick up changes from the cloud, even when new data is already available.
Even manual calls to fetchChanges() behave as if they’re throttled or delayed, rather than performing an immediate fetch.
Our questions:
Is this delay in automatic (and post-automatic manual) fetch behavior on macOS expected, or possibly a bug?
Are there specific macOS constraints that impact CKSyncEngine differently than on iOS?
Once CKSyncEngine has been initialized in automatic mode, is fetchChanges() no longer treated as a truly manual trigger?
Is there a recommended workaround to enable fast sync behavior on macOS — for example, by sticking to manual sync configuration and triggering sync using a CKSubscription-based mechanism when remote changes occur?
Any guidance, clarification, or experiences from other developers (or Apple engineers) would be greatly appreciated — especially regarding maintaining parity between iOS and macOS sync performance.
Thanks in advance!
                    
                  
                
                    
                      Hi,
I did cloudkit synchronization using swiftdata.
However, synchronization does not occur automatically, and synchronization occurs intermittently only when the device is closed and opened.
For confirmation, after changing the data in Device 1 (saving), when the data is fetched from Device 2, there is no change.
I've heard that there's still an issue with swiftdata sync and Apple is currently troubleshooting it, is the phenomenon I'm experiencing in the current version normal?
                    
                  
                
                    
                      I'm trying to set up an application using SwiftData to have a number of models backed by a local datastore that's not synced to CloudKit, and another set of models that is. I was able to achieve this previously with Core Data using multiple NSPersistentStoreDescription instances.
The set up code looks something like:
    do {
      let fullSchema = Schema([
        UnsyncedModel.self,
        SyncedModel.self,
      ])
      let localSchema = Schema([UnsyncedModel.self])
      let localConfig = ModelConfiguration(schema: localSchema, cloudKitDatabase: .none)
      let remoteSchema = Schema([SyncedModel.self])
      let remoteConfig = ModelConfiguration(schema: remoteSchema, cloudKitDatabase: .automatic)
      container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig)
    } catch {
      fatalError("Failed to configure SwiftData container.")
    }
However, it doesn't seem to work as expected. If I remove the synced/remote schema and configuration then everything works fine, but the moment I add in the remote schema and configuration I get various different application crashes. Some examples below:
A Core Data error occurred." UserInfo={Reason=Entity named:... not found for relationship named:...,
Fatal error: Failed to identify a store that can hold instances of SwiftData._KKMDBackingData<...>
Has anyone ever been able to get a similar setup to work using SwiftData?