iCloud & Data

RSS for tag

Learn how to integrate your app with iCloud and data frameworks for effective data storage

CloudKit Documentation

Posts under iCloud & Data subtopic

Post

Replies

Boosts

Views

Activity

A question on account change handler code in CKSyncEngine demo project
I have a quesiton on .accountChange handler code in CKSyncEngine demo project. Below is the code in handleAccountChange(): if shouldDeleteLocalData { try? self.deleteLocalData() // This error should be handled, but we'll skip that for brevity in this sample app. } if shouldReUploadLocalData { let recordZoneChanges: [CKSyncEngine.PendingRecordZoneChange] = self.appData.contacts.values.map { .saveRecord($0.recordID) } self.syncEngine.state.add(pendingDatabaseChanges: [ .saveZone(CKRecordZone(zoneName: Contact.zoneName)) ]) self.syncEngine.state.add(pendingRecordZoneChanges: recordZoneChanges) } IMHO, when user switches account, the most important thing is to reload data from the new account's document folder. However, I can't see this is done anywhere. In above code, if shouldDeleteLocalData is false, self.appData would still hold the previous account's local data. That seems very wrong. Am I missing something? It would be best if iOS restarts all applications when user switches account. If that's not the case (I guess so, otherwise there is no point to handle .accountChange in the app), I think application should implement an API to re-initialize itself. EDIT: after looking at the code again, I realize that the following code makes sure shouldDeleteLocalData is always true when user switching accounts. So the code doesn't leak the previous account's data, though I still think it has an issue - it doesn't load the new account's data. case .switchAccounts: shouldDeleteLocalData = true shouldReUploadLocalData = false
4
0
458
Nov ’24
iOS app transfer effect in app's documents
Hi, We are currently planning an app transfer between two developer accounts. We are concerned about files stored in the app's documents surviving the first update of the app released with the new developer account. Since app files in documents are part of the app's container, is it safe to assume that if the user just updates the app after the transfer, the files in documents would still be there? It is important for us to confirm this before we execute our plans Also, our app currently uses iCloud containers to save another set of files. Are these transferred with the app transfer or will the app lose access to these files? Are the files however accessible by users' by looking for them on their iCloud Drive? Thank you!
1
0
354
Sep ’24
Fetching strategies - Do not fetch redundant data. ETags, Lastmodified, own API? Recommendations, practice?
I am developing an Xcode app with a job feed, with profile view, with chat eg. I fetch using federatet queries to my microservices thru Apollo Router. Infront of the Apollo Router i Have a Kong that adds a X user ID, that the microservices use for personalized feed and other user info. The info is stored with SwiftData. My thought is that i should add a better way of controlling when i need to fetch. I have a “lastupdateAPI” with different entities (profile, profile picture eg). So when nothing has changed we do not fetch. But rather then using a own API for this, isnt ETag better? Or is it any other recommendations with Xcode Swiftui. Good strategies for not fetching what i already have?
2
0
715
Feb ’25
Swift 6 and NSPersistentCloudKitContainer
Hello all! I'm porting a ios15+ swiftui app to be compatible with Swift 6 and enabling strict concurrency checking gave me a warning that will be an error when switching to swift 6. I'm initializing a persistence controller for my cloud kit container: import CoreData struct PersistenceController { static let shared = PersistenceController() let container: NSPersistentCloudKitContainer init() { container = NSPersistentCloudKitContainer(name: "IBreviary") container.loadPersistentStores(completionHandler: { _, error in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy container.viewContext.automaticallyMergesChangesFromParent = true } } The warning is on the merge policy: Reference to var 'NSMergeByPropertyObjectTrumpMergePolicy' is not concurrency-safe because it involves shared mutable state; this is an error in the Swift 6 language mode I have no idea how to make this concurrency safe, nor I found a documentation entry to help me with this. Anyone have idea how to solve this? Thanks in advance V.
2
0
958
Sep ’24
SwiftData know how specific information
Re SwiftData: is my understanding correct : generally speaking and by default insert method inserts objects into the context and context automatically persist - e.g. inserts them into container while the delete method does not - it only deletes from context and context does not delete them from the container unless save is called ? It is not clear from the documentation nor from the definitions : public func delete<T>(model: T.Type, where predicate: Predicate<T>? = nil, includeSubclasses: Bool = true) throws where T : PersistentModel //How can I test it ? I’m keen to learn where I can confirm this in Apple’s documentation or official articles, code definitions, apart from experimenting or consulting third-party materials. Where does it explicitly state that SwiftData includes an automatic saving feature but does not offer automatic deletion? "Meet SwiftData" (WWDC23): Around the 14:30 mark, Apple mentions that SwiftData automatically saves changes "at opportune moments." But nothing is advised re deleting ? Are we supposed to be taking hints : "Build an app with SwiftData" (WWDC23): This session demonstrates using context.save() to persist changes after deleting an object, implies the idea that deletion isn't automatic How to truly learn if you do not have official materials ? This is exact Science, not archeology or history. I feel like a speleologist.
1
0
466
Oct ’24
dual predicate search using CoreData
I have a very simple CoreData model that has 1 entity and 2 attributes. This code works fine: .onChange(of: searchText) { _, text in evnts.nsPredicate = text.isEmpty ? nil :NSPredicate(format: "eventName CONTAINS %@ " , text ) but I'd like to also search with the same text string for my second attribute (which is a Date). I believe an OR is appropriate for two conditions (find either one). See attempted code below: evnts.nsPredicate = text.isEmpty ? nil : NSPredicate(format: "(eventName CONTAINS %@) OR (dueDate CONTAINS %i) " , text ) This crashes immediately %@ does the same. Is there a way to accomplish this? How is SwiftUI not an option below?
6
0
325
Mar ’25
Int128 fail in @Model with SwiftData
Swift recently added support for Int128. However, they do need NOT seem to be supported in SwiftData. Now totally possible I'm doing something wrong too. I have the project set to macOS 15 to use a UInt128 in @Model class as attribute. I tried using a clean Xcode project with Swift Data choosen in the macOS app wizard. Everything compiles, but it fails at runtime in both my app and "Xcode default" SwiftData: SwiftData/SchemaProperty.swift:380: Fatal error: Unexpected property within Persisted Struct/Enum: Builtin.Int128 with the only modification to from stock is: @Model final class Item { var timestamp: Date var ipv6: UInt128 init(timestamp: Date) { self.timestamp = timestamp self.ipv6 = 0 } } I have tried both Int128 and UInt128. Both fails exactly the same. In fact, so exactly, when using UInt128 it still show a "Int128" in error message, despite class member being UInt128 . My underlying need is to store an IPv6 addresses with an app, so the newer UInt128 would work to persist it. Since Network Framework IPv6Address is also not compatible, it seems, with SwiftData. So not a lot of good options, other an a String. But for an IPv6 address that suffers from that same address can take a few String forms (i.e. "0000:0000:0000:0000:0000:0000:0000:0000" =="0:0:0:0:0:0:0:0" == "::") which is more annoying than having a few expand Int128 as String separator ":". Ideas welcomed. But potentially a bug in SwiftData since Int128 is both a Builtin and conforms to Codable, so from my reading it should work.
7
0
519
Feb ’25
Any SwiftData change updates every SwiftUI view
Perhaps I just have the wrong expectations, but I discovered some odd behavior from SwiftData that sure seems like a bug to me... If you make any change to any SwiftData model object — even just setting a property to its current value — every SwiftUI view that uses SwiftData is rebuilt. Every query and every entity reference, even if the property was set on a model class that is completely unrelated to the view. SwiftUI does such a good job of optimizing UI updates that it's hard to notice the issue. I only noticed it because the updates were triggering my debug print statements. To double-check this, I went back to Apple's new iOS app template — the one that is just a list of dated items — and added a little code to touch an unrelated record in the background: @Model class UnrelatedItem { var name: String init(name: String) { self.name = name } } @main struct jumpyApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Item.self, UnrelatedItem.self ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() init() { let context = sharedModelContainer.mainContext // Create 3 items at launch so we immediately have some data to work with. if try! context.fetchCount(FetchDescriptor<Item>()) == 0 { for _ in 0..<3 { let item = Item(timestamp: Date()) context.insert(item) } } // Now create one unrelated item. let unrelatedItem = UnrelatedItem(name: "Mongoose") context.insert(unrelatedItem) try? context.save() // Set up a background task that updates the unrelated item every second. Task { while true { try? await Task.sleep(nanoseconds: 1_000_000_000) Task { @MainActor in // We don't even have to change the name or save the contxt. // Just setting the name to the same value will trigger a change. unrelatedItem.name = "Mongoose" } } } } var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } I also added a print statement to the ContentView so I could see when the view updates. struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] var body: some View { NavigationSplitView { List { let _ = Self._printChanges() ... The result is that the print statement logs 2 messages to the debug console every second. I checked in iOS 17, 18.1, and 18.2, and they all behave this way. Is this the intended behavior? I thought the whole point of the new Observation framework in iOS 17 was to track which data had changed and only send change notifications to observers who were using that data.
3
0
1.2k
Mar ’25
How to use notification to notify shared container changes in cloudkit?
I would like to create a private container and share a zone between two users with different iCloud accounts. All changes made by one would be notified with push notifications to the other user's db. Both could change the same information. Exactly as it is done in this apple project. https://developer.apple.com/documentation/cloudkit/shared_records/sharing_cloudkit_data_with_other_icloud_users However, I have been reading this code for days and I am stuck on it, it is extremely complicated for my level. I would really like to know if there is any simple project that uses the same idea to build this logic with swiftui.
3
0
1.2k
Oct ’24
CloudKit not working on actual iOS device
I've developed an app that contains an inbox that displays message from a CloudKit container. Works perfectly on simulator. Once I tried to run it on a phone..in Xcode debug environment and TestFlight it is unable to complete any transactions with production database. I'm running out of ideas. So far I have tried: Verify settings between debug and release in Signing & Capabilities Add CloudKit.framework to Framework, Libraries, and Embedded Content Verify record and key names verify .entitlements files Please help!
3
0
632
Nov ’24
[SwiftData] How to use @Query to get the first 7 elements in the list
Maybe I didn't find the relevant instructions. In my code, I only want to get the first 7 elements. At present, my code is as follows: @Query(sort:\Record.date, order: .reverse) private var records:[Record] But I wonder if once the number of records is large, will it affect the efficiency? In View, it is enough for me to count the first 7 elements in records. What should I do?
1
0
416
Nov ’24
UndoManager with SwiftData Not Registering Single Undo Actions Properly in macOS Sonoma 14.x
I am encountering an issue with the UndoManager functionality in a SwiftUI application that integrates SwiftData for persistence. This issue occurs specifically in macOS 14 (Sonoma) but works as expected on macOS 15 (Sequoia). The focused test app I have prepared for demonstration allows users to create ParentItem objects, and for each ParentItem, users can add multiple ChildItem objects. The undo functionality (via Cmd+Z) is not working as expected in Sonoma. When I try to undo a ChildItem addition, the UndoManager does not revert just the last ChildItem added, but instead removes all ChildItems that were added in that session. Expected Behavior On macOS 14 (Sonoma), I expect the UndoManager to undo only the most recent transaction (in this case, a single ChildItem insert), similar to how it functions on macOS 15 (Sequoia). Each ChildItem insertion should be treated as a separate undoable action. Current Behavior In macOS Sonoma, pressing Cmd+Z undoes the entire list of ChildItems added to a ParentItem in the current session, rather than just the most recent ChildItem. This appears to be an issue with undo grouping, but I’ve confirmed that no explicit grouping is being used. Question Is this an issue with UndoManager in macOS Sonoma, particularly in how it interacts with SwiftData persistence? What changes should I make to ensure that each ChildItem insert is treated as an individual undo action in macOS Sonoma, just as it works in Sequoia? Any guidance on isolating the issue or recommended workarounds would be appreciated. I would expect that undo actions for each child addition would be treated as separate transactions, not grouped. Steps Taken to Solve the Problem I attempted to manually save the model context (modelContext.save()) after each ChildItem insert to ensure proper persistence. I also verified that UndoManager was not grouping operations explicitly by calling beginUndoGrouping() or endUndoGrouping() myself. This issue seems to be tied specifically to macOS Sonoma, as it does not occur on macOS Sequoia, where undoing behaves as expected. Conditions macOS 14 Sonoma: The issue occurs consistently. macOS 15 Sequoia: The issue does not occur. This issue appears to be independent of hardware, as I’ve tested it on multiple machines. APIs/Features Potentially Involved UndoManager in a SwiftUI application SwiftData for persistence (using modelContext.save()) macOS version-specific behavior Steps to reproduce Clone test project (https://github.com/Maschina/SwiftDataUndoManagerExample), compile and run Create a new ParentItem in the app (via plus toolbar button in the sidebar). Add multiple ChildItems to the ParentItem (via plus toolbar button in the content / middle column of the navigation split view). Press Cmd+Z to undo the last addition.
2
0
1.1k
Nov ’24
[SwiftData] How to get the first 7 elements by using @Query?
Maybe I didn't find the relevant instructions. In my code, I only want to get the first 7 elements. At present, my code is as follows: @Query(sort:\Record.date, order: .reverse) private var records:[Record] But I wonder if once the number of records is large, will it affect the efficiency? In View, it is enough for me to count the first 7 elements in records. What should I do?
1
0
790
Nov ’24
How can my app access any cloud drive app?
My app needs to share data files with multiple devices owned by a single user. I also want to implement this mechanism without setting up a server. Therefore, I want to make it read/write to local data on the user's own cloud drive (e.g. iCloud, Google Drive, One Drive, Dropbox) and read/use them as needed. I have tried “.fileImporter” to get the URL, but the button is grayed out and cannot be opened. Sorry for my poor English. struct FilePathSettingView: View { @State private var isPickerPresented: Bool = false var fileControll = FileControll() var body: some View { VStack { Text("Storage Setting") Button(action:{ isPickerPresented = true }) { Text("Select place") } .fileImporter( isPresented: $isPickerPresented, allowedContentTypes: [.directory, .folder], allowsMultipleSelection: false, onCompletion: { result in switch result { case .success(let urls): guard let url = urls.first else { return } let accessGranted = url.startAccessingSecurityScopedResource() defer { if accessGranted { url.stopAccessingSecurityScopedResource() } } guard accessGranted else { print("Failed to access security-scoped resource.") return } fileControll.createDirectoryStructure(in: url) case .failure(let error): print("Failed to select directory: \(error.localizedDescription)") } } ) } } }
2
0
800
Oct ’24
SwiftData: Failed to decode a composite attribute
I changed an enum value from this: enum Kind: String, Codable, CaseIterable { case credit } to this: enum Kind: String, Codable, CaseIterable { case credit = "Credit" } And now it fails to load the data. This is inside of a SwiftData model. I get why the error is occurring, but is there a way to resolve this issue without having to revert back or delete the data? Error: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "Cannot initialize Kind from invalid String value credit", underlyingError: nil))
3
0
793
Nov ’24
Mapping model not found if the attribute has "Preserve after deletion" enabled
I am trying to migrate my Core Data model to a new version with a new attribute added to it. Since my app supports macOS 13 I am not able to use the newly introduced Staged migrations. After much digging I found that the app is not able to find the Mapping Model when one of the attribute has "Preserve after deletion" enabled. I have enabled migration debbuging using com.apple.CoreData.MigrationDebug 1 I am getting following error error: CoreData: error: (migration) migration failed with error Error Domain=NSCocoaErrorDomain Code=134140 "Persistent store migration failed, missing mapping model." What is the way out here?
6
0
868
Feb ’25
App Transfer - iCloud and legacy apps
Juust before I initiate an App Transfer... We have sandboxed 'mobile' versions of our app (iOS and mac App) to transfer to the surviving company. However, we also have a 'full' non-sandboxed legacy desktop dmg version of the app, available for Mac (and Win). This has access to the same iCloud folder So the question is, what happens to the iCloud app folder on the Mac if they are only using this desktop version, once the transfer takes place? Will it remain visible on the Mac, and will it remain accessible by the desktop version if so? I expect that although the iCloud entitlement is transferred, as it is another Team ID, the legacy app will not be able to read/write without user prompted permission. What I hope at the least, is that the folder doesn't become invisible on that machine...
2
0
329
Oct ’24
What is CloudKit error: AssetUploadTokenRetrieveRequest request size exceeds limit
Some of my customer get the following CloudKit error (I cannot reproduce is myself). Failed to modify some records (CKErrorDomain:2) userInfo: CKErrorDescription:Failed to modify some records CKPartialErrors:{ "<CKRecordID: ooo; recordName=ooo, zoneID=ooo:__defaultOwner__>" = "<CKError 0x600003809ce0: \"Limit Exceeded\" (27/2023); server message = \"AssetUploadTokenRetrieveRequest request size exceeds limit\"; op = ooo; uuid = ooo; container ID = \"ooo\">" This is a CKError.limitExeeded error. I create 200 or less records in a batch operation. So I am below the 400 limit. Searching the Internet for "AssetUploadTokenRetrieveRequest request size exceeds limit": 0 results Can anyone give me a hint?
5
0
724
Apr ’25
How to get a real time and date (not device time) for query?
I need to know the current date to query CloudKit data with it, like: let predicate = NSPredicate(format: "publishedAt <= %@", currentDateAndTime) I don't need high precision, even +/- a few minutes is fine, but I can't rely on device's time since the user can manually change it. Researching this myself I see that the most reliable method is to get the date from the server. There are NTP servers, but accessing them requires additional libraries which adds complexity. TrueTime (last updated 6 years ago) and Kronos (updated like once a year) seem outdated, given how much Swift has changed in the past years. I can make an HTTP request to a website like Google or Apple and read the current time from its headers. But I don't know if this method is reliable. I know I can create a dummy record in CloudKit, update it, and read its modificationDate. But it feels hacky. Maybe there is another way to fetch the current date directly from CloudKit? It feels like it should be easy and there is a straightforward solution, but I just can't find it.
1
0
582
Jan ’25
Core Data modifications not saved in two of three tables
I'm a bit lost because of a problem I never experienced before: I create entries in 3 Core Data tables and link them. As long as the app is open, everything is fine, I can see the database entries in the three tables. Once the App is closed and restarted, however, the new entries in two of the three tables are gone. I use Core Data for data storage and DB Browser for SQLite for inspecting the database running in the Simulator. Here's the relevant function where all Core Data handling happens: /** Creates a new ComposedFoodItem from the ComposedFoodItemViewModel. Creates the related FoodItem and the Ingredients. Creates all relationships. - Parameter composedFoodItemVM: The source view model. - Returns: A Core Data ComposedFoodItem; nil if there are no Ingredients. */ static func create(from composedFoodItemVM: ComposedFoodItemViewModel, generateTypicalAmounts: Bool) -> ComposedFoodItem? { debugPrint(AppDelegate.persistentContainer.persistentStoreDescriptions) // The location of the .sqlite file let moc = AppDelegate.viewContext // Create new ComposedFoodItem (1) let cdComposedFoodItem = ComposedFoodItem(context: moc) // No existing composed food item, therefore create a new UUID cdComposedFoodItem.id = UUID() // Fill data cdComposedFoodItem.amount = Int64(composedFoodItemVM.amount) cdComposedFoodItem.numberOfPortions = Int16(composedFoodItemVM.numberOfPortions) // Create the related FoodItem (2) let cdFoodItem = FoodItem.create(from: composedFoodItemVM, generateTypicalAmounts: generateTypicalAmounts) // Relate both (3) cdComposedFoodItem.foodItem = cdFoodItem // Add cdComposedFoodItem to composedFoodItemVM composedFoodItemVM.cdComposedFoodItem = cdComposedFoodItem // Add new ingredients (4) if let cdIngredients = Ingredient.create(from: composedFoodItemVM) { cdComposedFoodItem.addToIngredients(NSSet(array: cdIngredients)) // Save new composed food item try? moc.save() // Return the ComposedFoodItem return cdComposedFoodItem } else { // There are no ingredients, therefore we delete it again and return nil moc.delete(cdComposedFoodItem) try? moc.save() return nil } } What the function does: Creates a new entry in table ComposedFoodItem Creates another new entry in another table FoodItem Relates both entries Creates another 1..n entries in a third table Ingredient and links these to the entry created in step 1 All this works fine, I can see all relations and entries in the database. Then I quit and restart the app. The entry created in step 2 is still there, but the entries created in steps 1 and 4 are gone, as well as the relationships (of course). My suspicion: I recently implemented a Core Data migration from Data Model version 1 ("EasyFPU") to version 2 ("EasyFPU 2"). In this migration, I have two custom migration policies for exactly the two tables, which are not stored. The migration policies are pretty simple (and identical for both tables): /** No Ingredient is created in the destination model, i.e., there will be no Ingredients */ override func createDestinationInstances(forSource sourceIngredient: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws { // Do nothing on purpose debugPrint("Not migrating Ingredient with ID: \((sourceIngredient as? Ingredient)?.id.uuidString ?? "unknown")") } And what I suspect is, that this migration policies are somehow called when restarting the app, but I have no idea why, because the migration has already happened before. If I set a breakpoint in the debugPrint line of the code snippet above, I actually never reach this breakpoint - as expected. Nevertheless are the two tables Ingredient and ComposedFoodItem empty after restart. My AppDelegate Core Data persistentContainer variable looks like this: lazy var persistentContainer: NSPersistentCloudKitContainer = { let container = NSPersistentCloudKitContainer(name: "EasyFPU") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }() I tried to replace "EasyFPU" with "EasyFPU 2", but this apparently is not the version, but the container name. Any idea? Thanks in advance!
1
0
353
Sep ’24