Hi all,
In my SwiftUI / SwiftData / Cloudkit app which is a series of lists, I have a model object called Project which contains an array of model objects called subprojects:
final class Project1
{
var name: String = ""
@Relationship(deleteRule: .cascade, inverse: \Subproject.project) var subprojects : [Subproject]?
init(name: String)
{
self.name = name
self.subprojects = []
}
}
The user will select a project from a list, which will generate a list of subprojects in another list, and if they select a subproject, it will generate a list categories and if the user selects a category it will generate another list of child objects owned by category and on and on.
This is the pattern in my app, I'm constantly passing arrays of model objects that are the children of other model objects throughout the program, and I need the user to be able to add and remove things from them.
My initial approach was to pass these arrays as bindings so that I'd be able to mutate them. This worked for the most part but there were two problems: it was a lot of custom binding code and when I had to unwrap these bindings using init?(_ base: Binding<Value?>), my program would crash if one of these arrays became nil (it's some weird quirk of that init that I don't understand at al).
As I'm still learning the framework, I had not realized that the @model macro had automatically made my model objects observable, so I decided to remove the bindings and simply pass the arrays by reference, and while it seems these references will carry the most up to date version of the array, you cannot mutate them unless you have access to the parent and mutate it like such:
project.subcategories?.removeAll { $0 == subcategory }
project.subcategories?.append(subcategory)
This is weirding me out because you can't unwrap subcategories before you try to mutate the array, it has to be done like above. In my code, I like to unwrap all optionals at the moment that I need the values stored in them and if not, I like to post an error to the user. Isn't that the point of optionals? So I don't understand why it's like this and ultimately am wondering if I'm using the correct design pattern for what I'm trying to accomplish or if I'm missing something? Any input would be much appreciated!
Also, I do have a small MRE project if the explanation above wasn't clear enough, but I was unable to paste in here (too long), attach the zip or paste a link to Google Drive. Open to sharing it if anyone can tell me the best way to do so. Thanks!
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
How does SwiftData work with background operations? CoreData had background context that could be used to avoid UI hang for heavy operations.
Is there an equivalent in SwiftData, and if so, do I have to merge changes or does it save directly to persistent store?
Hey there,
Can we bundle our app with our own version of SQLite with extensions that we want. From what I've seen, we aren't allowed to add extensions to the built in IOS SQLite, so would this be the only way to use extensions. I ask this because I want to use the spell fix extension.
I couldn't find a lot of people talking about adding SQLite extensions.
Thank you!
Topic:
App & System Services
SubTopic:
iCloud & Data
I work on an app that saves data to the Documents folder in the users iCloud Drive. This uses the iCloud -> iCloud Documents capability with a standard container.
We've noticed an issue where a user will delete the apps data by doing to Settings > {Name} > iCloud > Storage > App Name > select "delete data from iCloud", and then our app can no longer write to or create the Documents folder.
Once that happens, we get this error:
Error Domain=NSCocoaErrorDomain Code=513 "You don't have permission to save the file "Documents" in the folder "iCloud~your~bundle~identifier"." UserInfo={NSFilePath=/private/var/mobile/Library/Mobile Documents/iCloud~your~bundle~identifier/Documents, NSURL=file:///private/var/mobile/Library/Mobile%20Documents/iCloud~your~bundle~identifier/Documents, NSUnderlyingError=0x1102c7ea0 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}
This is reproducible using the sample project here https://developer.apple.com/documentation/uikit/synchronizing-documents-in-the-icloud-environment.
Steps to reproduce in that project:
Tap the plus sign in the top right corner to create a new document
Add a document name and tap "Save to Documents"
Go to Settings > {Name} > iCloud > Storage > SimpleiCloudDocument App Name > select "delete data from iCloud"
Reopen the app and repeat steps 1-2
Observe error on MainViewController+Document.swift:59
Deleting and reinstalling the app doesn't seem to help.
Topic:
App & System Services
SubTopic:
iCloud & Data
DESCRIPTION
I have an App use iCloud to save data.
The App had a CoreData ManagedObject 'Product', 'Product' Object had an attribute name 'count' and it is a Double Type.
I need to synchronises 'count' property across multiple devices.
for example:
I have a devices A、B.
A device set 'Product.count' = 100.
B device set 'Product.count' = 50.
I hope the 'Product.count' == 150 that results.
how to synchronises the 'Product.count' == 150 for multiple devices.
If I have more devices in future, How to get the latest 'Product.count' that it is correct result.
Hi everyone,
I’m currently developing a SwiftUI app that uses SwiftData with CloudKit sharing enabled. The app works fine on my own Apple ID, and local syncing with iCloud is functioning correctly — but sharing with other Apple IDs consistently fails.
Setup:
SwiftUI + SwiftData using a ModelContainer with .shared configuration
Sharing UI is handled via UICloudSharingController
iCloud container: iCloud.com.de.SkerskiDev.FoodGuard
Proper entitlements enabled (com.apple.developer.icloud-services, CloudKit, com.apple.developer.coredata.cloudkit.containers, etc.)
Automatic provisioning profiles created by Xcode
Error:<CKError 0x1143a2be0: "Bad Container" (5/1014);
"Couldn't get container configuration from the server for container iCloud.com.de.SkerskiDev.FoodGuard">
What I’ve tried:
Verified the iCloud container is correctly created and enabled in the Apple Developer portal
Checked bundle identifier and container settings
Rebuilt and reinstalled the app
Ensured correct iCloud entitlements and signing capabilities
Questions:
Why does CloudKit reject the container for sharing while local syncing works fine?
Are there known issues with SwiftData .shared containers and multi-user sharing?
Are additional steps required (App Store Connect, privacy settings) to allow sharing with other Apple IDs?
Any advice, experience, or example projects would be greatly appreciated. 🙏
Thanks!
Sebastian
I'm building a macOS + iOS SwiftUI app using Xcode 14.1b3 on a Mac running macOS 13.b11. The app uses Core Data + CloudKit.
With development builds, CloudKit integration works on the Mac app and the iOS app. Existing records are fetched from iCloud, and new records are uploaded to iCloud. Everybody's happy.
With TestFlight builds, the iOS app has no problems. But CloudKit integration isn't working in the Mac app at all. No existing records are fetched, no new records are uploaded.
In the Console, I see this message:
error: CoreData+CloudKit: Failed to set up CloudKit integration for store: <NSSQLCore: 0x1324079e0> (URL: <local file url>)
Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.cloudd was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.cloudd was invalidated: failed at lookup with error 159 - Sandbox restriction.}
I thought it might be that I was missing the com.apple.security.network.client entitlement, but adding that didn't help.
Any suggestions what I might be missing? (It's my first sandboxed Mac app, so it might be really obvious to anyone but me.)
I have an issue in my app, where the crashing frame is an assertionFailure in BackingData.set inside SwiftData framework. My own app doesn't appear until frame 14. I have no idea what causes this, or even how to create a reproducible project as this only happens on some devices.
The frame prior to the assertionFailure is this:
#1 (null) in BackingData.set(any:value:) ()
It seems like there is a backing data encoding happening in my Model class, and some value is causing it to fail. The model being accessed is through a relationship, and the frame in the app crashing is along the lines of
Text(parent.child.name)
Obviously, something is wrong in how I have made child, but the part that stand out to me is the assertionFailure in a release build
Hello everyone,
I'm trying to adopt the new Staged Migrations for Core Data and I keep running into an error that I haven't been able to resolve.
The error messages are as follows:
warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Movie' so +entity is unable to disambiguate.
warning: 'Movie' (0x60000350d6b0) from NSManagedObjectModel (0x60000213a8a0) claims 'Movie'.
error: +[Movie entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
This happens for all of my entities when they are added/fetched. Movie is an abstract entity subclass, and it has the error error: +[Movie entity] Failed to find which is unique to the subclass entities, but this occurs for all entities.
The NSPersistentContainer is loaded only once, and I set the following option after it's loaded:
storeDescription.setOption(
[stages],
forKey: NSPersistentStoreStagedMigrationManagerOptionKey
)
The warnings and errors only appear after I fetch or save to context. It happens regardless of whether the database was migrated or not. In my test project, using the generic NSManagedObject with NSEntityDescription.insertNewObject(forEntityName: "MyEntity", into: context) does not cause the issue. However, using the generic NSManagedObject is not a viable option for my app.
Setting the module to "Current Project Module" doesn't change anything, except that it now prints "claims 'MyModule.Show'" in the warnings. I have verified that there are no other entities with the same name or renameIdentifier.
Has anyone else encountered this issue, or can offer any suggestions on how to resolve it?
Thanks in advance for any help!
I built a SwiftData App that relies on CloudKit to synchronize data across devices.
That means all model relationships must be expressed as Optional.
That’s fine, but there is a limitation in using Optional’s in SwiftData SortDescriptors (Crashes App)
That means I can’t apply a SortDescriptor to ModelA using some property value in ModelB (even if ModelB must exist)
I tried using a computed property in ModelA that referred to the property in ModelB, BUT THIS DOESN”T WORK EITHER!
Am I stuck storing redundant data In ModelA just to sort ModelA as I would like???
I have implemented CKSyncEngine synchronization, and it works well. I can update data on one device and see the changes propagate to another device quickly. However, the initial sync when a user downloads the app on a new device is a significant issue for both me and my users.
One problem is that the sync engine fetches deletion events from the server. On a new device, the local database is empty, so these deletions are essentially no-ops. This would not be a big problem if there were only a few records or if it was fast. I measured the initial sync and found that there are 150 modified records and 62,168 deletions. Counting these alone takes over five minutes, even without processing them. The deletions do nothing because the local database has nothing to delete, yet they still add a significant delay.
I understand that the sync engine ensures consistency across all devices, but five minutes of waiting with the app open just to insert a small number of records is excessive. The problem would be worse if there were tens of thousands of new records to insert, since downloading and saving the data would take even longer.
This leads to a poor user experience. Users open the app and see data being populated for several minutes, or they are stuck on a screen that says the data is being synchronized with iCloud.
I am wondering if there is a way to make the sync engine ignore deletion events when the state serialization is nil. Alternatively, is there a recommended method for handling initial synchronization more efficiently?
One idea I considered is storing all the data as a backup in iCloud Documents, along with the state serialization at that point in time. When a user opens the app for the first time, I could download the file, extract the data, and set the state serialization to the saved value. I am not sure if this would work. I do not know if state serialization is tied to the device or if it only represents the point where the sync engine left off. My guess is that it might reference some local device storage.
I am not sure what else to try. I could fetch all data using CloudKit, create the sync engine with an empty state serialization, and let it fetch everything again, but that would still take a long time.
My records are very small, mostly a date when something happened and an ID referencing the parent. Since the app tracks watched episodes, I only store the date the user watched the episode and the ID of that episode.
Hello,
I have 3 model versions and I'm trying to step through migration.
Version 2 makes significant changes to v1. As a result, I've renamed the entities in question by appending _v2 to their name, as the data isn't important to retain.
v3, remove's the appended version number from v2.
Setting the .xcdatamodeld to v3 and the migrations steps array as follows causes the app to error
[
NSLightweightMigrationStage([v1]),
NSLightweightMigrationStage([v2]),
NSLightweightMigrationStage([v3]),
]
CoreData: error: <NSPersistentStoreCoordinator: 0x10740d680>: Attempting recovery from error encountered during addPersistentStore: 0x10770f8a0 Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration."
An error occurred during persistent store migration. Cannot merge multiple root entity source tables into one destination entity root table.
I find this odd because if I run the migration independently across app launches, the migration appears to drop the no longer used tables in v2, then re-add them back in v3. So it seems to me that something is not finishing completely with the fully stepped through migration.
--
I'm also unable to understand how to use NSCustomMigrationStage I've tried setting it to migrate from v1, to v2, but I'm getting a crash with error
Duplicate version checksums across stages detected
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
Here is what I thought
I want to give each user a unique container, when the user login or register, the user could isolate their data in specific container.
I shared the container in a singleton actor, I found it's possible to update the container in that actor.
But I think it won't affect the modelContext which is in the Environment.
Does SwiftData allow me or recommend to do that?
This simple test fails in my project. Similar code in my application also crashes.
How do I debug the problem?
What project settings are required. I have added SwiftData as a framework to test (and application) targets?
Thanks,
The problem is with:
modelContext.insert(item)
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
import XCTest
import SwiftData
@Model
class FakeModel {
var name: String
init(name: String) { self.name = name }
}
@MainActor
final class FakeModelTests: XCTestCase {
var modelContext: ModelContext!
override func setUp() {
super.setUp()
do {
let container = try ModelContainer(for: FakeModel.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))
modelContext = container.mainContext
} catch {
XCTFail("Failed to create ModelContainer: \(error)")
modelContext = nil
}
}
func testSaveFetchDeleteFakeItem() {
guard let modelContext = modelContext else {
XCTFail("ModelContext must be initialized")
return
}
let item = FakeModel(name: "Test")
modelContext.insert(item)
let fetchDescriptor = FetchDescriptor<FakeModel>()
let items = try! modelContext.fetch(fetchDescriptor)
XCTAssertEqual(items.count, 1)
XCTAssertEqual(items.first?.name, "Test")
modelContext.delete(item)
let itemsAfterDelete = try! modelContext.fetch(fetchDescriptor)
XCTAssertEqual(itemsAfterDelete.count, 0)
}
}
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)
}
}
Hello,
I recently published an app that uses Swift Data as its primary data storage. The app uses concurrency, background threads, async await, and BLE communication.
Sadly, I see my app incurs many fringe crashes, involving EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, EXC_BREAKPOINT, etc.
I followed these guidelines:
One ModelContainer that is stored as a global variable and used throughout.
ModelContexts are created separately for each task, changes are saved manually, and models are not passed around.
Threads with different ModelContexts might manipulate and/or read the same data simultaneously.
I was under the impression this meets the usage requirements.
I suspect perhaps the issue lies in my usage of contexts in a single await function, that might be paused and resumed on a different thread (although same execution path). Is that the case? If so, how should SwiftData be used in async scopes?
Is there anything else particularly wrong in my approach?
relationshipKeyPathsForPrefetching in SwiftData does not seem to work here when scrolling down the list. Why?
I would like all categories to be fetched while posts are fetched - not while scrolling down the list.
struct ContentView: View {
var body: some View {
QueryList(
fetchDescriptor: withCategoriesFetchDescriptor
)
}
var withCategoriesFetchDescriptor: FetchDescriptor<Post> {
var fetchDescriptor = FetchDescriptor<Post>()
fetchDescriptor.relationshipKeyPathsForPrefetching = [\.category]
return fetchDescriptor
}
}
struct QueryList: View {
@Query
var posts: [Post]
init(fetchDescriptor: FetchDescriptor<Post>) {
_posts = Query(fetchDescriptor)
}
var body: some View {
List(posts) { post in
VStack {
Text(post.title)
Text(post.category?.name ?? "")
.font(.footnote)
}
}
}
}
@Model
final class Post {
var title: String
var category: Category?
init(title: String) {
self.title = title
}
}
@Model final class Category {
var name: String
init(name: String) {
self.name = name
}
}
Since publishing new record types to my CloudKit schema in production, a previously unchanged record type has stopped indexing new records.
While records of this type are successfully saved without errors, they are not returned in query results—they can only be accessed directly via their recordName. This issue occurs exclusively in the Production environment, both in the CloudKit Console and our iOS app.
The problem began on July 21, 2025, and continues to persist. The issue affects only new records of this specific record type; all other types are indexing and querying as expected.
The affected record's fields are properly configured with the appropriate index types (e.g., QUERYABLE) and have been not been modified prior to publishing the schema.
With this, are there any steps I should take to restore indexing functionality for this record type in Production? There have been new records inserted, and I would prefer to not have to reset the production database, if possible.
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
Cloud and Local Storage
CloudKit Dashboard
CloudKit Console
Hello,
I have an asset pack that I'm use to periodically distribute a sqlite database thats being used to an NSPersistentStore.
Because the database is over a few GBs, and the files in an AssetPack are not mutable, I have to stream the database into a temporary file, then replace my NSPersistentStore.
This requires that the user has 3x the storage available of the database, and permanently uses twice to storage needed.
I'd like:
To be able to mark a URL/File to be accessible for read/write access
To be able to mark a file / URL as consumed when it's no needed. So that it can be cleared from the user storage while still maintaining an active subscription to the asset pack for updates.
Thank you
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
Files and Storage
On demand resources
Core Data
Background Assets