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

Core Data not returning results in ShieldConfiguration Extension, but works fine in other extensions
Hi everyone, I’m using Core Data in several extensions (DeviceActivityMonitor, ShieldAction, and ShieldConfiguration). It works perfectly in DeviceActivityMonitor and ShieldAction. I’m able to successfully fetch data and log the correct count using a fetch request. However, when I try the same setup in the ShieldConfiguration extension, the fetch request always returns 0 results. The CoreData and App Group setup appears to be correct since the first two extensions fetch the expected data. I’ve also previously tested storing the CoreData objects separately in a JSON-FIle using FileManager and it worked without issues—though I’d prefer not to handle manual encoding/decoding if possible. The documentation mentions that the extension runs in a sandbox, restricting network requests or moving sensitive content. But shouldn’t reading data (from a shared App Group, for instance) still be possible within the sandbox, as it is the case with the Files, what is the difference there? In my case, I only need to read the data, as modifications can be handled via ShieldActionExtension. Any help would be greatly appreciated!
2
0
979
Oct ’24
Error message when opening a SwiftData ModelContainer
I'm seeing these errors in the console when calling ModelContainer(for:migrationPlan:configurations) for iOS 18: error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again. CoreData: error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again. Is this anything to be concerned about? (Side note: "version" is misspelled in "verison checksum")
4
1
2.2k
Oct ’24
ckqueryoperation in CloudKit crashing
Use CloudKit's ckqueryoperation's recordmatchedblock in Swift 6.0, which always crashes, but works fine in Swift 5: func fetchAllRecords() async throws { let predicate = NSPredicate(format: "Topics = %@", "Integrations") let query = CKQuery(recordType: "PureMList", predicate: predicate) let operation = CKQueryOperation(query: query) operation.recordMatchedBlock = { recordID, result in switch result { case .success(let record): DispatchQueue.main.async { // Ensure UI updates happen here print("Fetched record: \(record)") // Update your UI elements here } case .failure(let error): // Handle the error print("Error fetching record with ID \(recordID): \(error)") } } // Ensure you're using the correct database publicDatabase.add(operation) }
2
0
490
Oct ’24
iOS 18 SwiftData Bug: Codable Models Cause Relationship Mapping Error
Here we have yet another bug, I suppose, in SwiftData that happens on iOS18 but it is not an issue on iOS17. There are 2 models defined as follows @Model final public class Note: Identifiable, Codable, Hashable { public private(set) var uuid = UUID().uuidString var heading: String = "" var tags: [Tag]? init(heading: String = "") { self.heading = heading } required public init(from decoder: Decoder) throws { ... } public func encode(to encoder: Encoder) throws { ... } } @Model final public class Tag: Identifiable, Codable { var name: String = "" @Relationship(deleteRule: .nullify, inverse: \Note.tags) var notes: [Note]? init(_ name: String) { self.name = name } required public init(from decoder: Decoder) throws { … } public func encode(to encoder: Encoder) throws { ... } } and a function o add new tags as follows private func addTags(note: Note, tagNames: [String]) { if note.tags == nil { note.tags = [] } for tagName in tagNames { if let tag = fetchTag(tagName) { if !note.tags!.contains(where: {$0.name == tagName}) { note.tags!.append(tag) } } else { // The following line throws the exception on iOS18 when Tag conforms to Codable: // Illegal attempt to map a relationship containing temporary objects to its identifiers. note.tags!.append(Tag(tagName)) } } } This code works perfectly well on iOS17 but on iOS18 I get the exception “Illegal attempt to map a relationship containing temporary objects to its identifiers.” What I noticed that this happens only when Tag model conforms to Codable protocol. Is it a bug? It looks like, otherwise we've got some undocumented changes have been made. In my previous post I mentioned about the other issue about ModelContext that is broken too on iOS18 - I mean it works perfectly well on iOS17. Demo app with an example how to workaround this problem is available here on GitHub. Repro steps: Add a note with some tags (separated by space) Edit this note and add a new tag (tag that does not exists in database) and tap Save. You should noticed that the tag hasn't been added. It works occasionally but hardly to be seen.
3
5
1.1k
Oct ’24
Thumbnails for images saved in core data
I'm trying to look at what the best way to do thumbnails for images that are saved in core data, which are being synced across multiple devices. I know I can save a lower quality version into core data, but I'm wondering if there's a better way of doing it. I've come across quick look thumbnailing which looks like what I want, but I'm not sure if it can be adapted for core data as its using file paths, whereas the images are stored in a data type property in core data. From what I can tell, I'd have to save the image locally, produce the thumbnail, then delete the local image
0
0
433
Oct ’24
CloudKit sharing limits?
When you share records, they get put into a new zone. Creating a zone for the share makes sense to me, but I thought I read that there was a limit to the number of zones one could have (something like 1024). Does this mean a user can’t share more than 1024 separate items with 1024 different people? I assume any other items shared with the same group end up in an existing zone.
0
0
371
Oct ’24
SwiftUI previews and CloudKit sharing
The SwiftUI templates provided by Xcode typically create an in-memory store for preview purposes. I started from one of these templates and added the necessary code for working with CloudKit shares, but now the existing preview store creation gets runtime errors I'm struggling to understand. The ultimate error is: FAULT: NSInternalInconsistencyException: Unsupported feature in this configuration; { store = "<NSSQLCore: 0x12e26b170> (URL: file:///dev/null)"; } There are other things in the log like: warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Trip' so +entity is unable to disambiguate. This might be due in part to the normal full stack being instantiated during a unit test, but that was the only way I could step through the code to try to see what was causing the SwiftUI preview to crash. I can't build the full core data stack as normal, because then the unit tests and previews pollute the real store.
1
0
529
Oct ’24
CKContainer shareParticipant() 'missing' nameComponents
My App requires access to iCloud. I used to be able to get the User's name components (family+given name) using: let dummyZone = CKRecordZone (zoneName: UUID().uuidString) let dummyShare = CKShare (recordZoneID: dummyZone.zoneID) Persistence.logger.notice ("\(#function): Dummy Zone: \(dummyZone.zoneID.zoneName)") // Save the dummyZone and then the dummyShare (for/in the dummyZone) let _ = try await container.privateCloudDatabase.save (dummyZone) let _ = try await container.privateCloudDatabase.save (dummyShare) // Extract the dummyShare's owner's identity - which is 'us/me' let userIdentity = dummyShare.owner.userIdentity where the resulting userIdentity had a filled out nameComponents. Now, recently, it seems to be empty. Did something change in the interfaces? I've also tried, more directly: let userRecordID = try await container.userRecordID() let userParticipant = try await container.shareParticipant(forUserRecordID: userRecordID) let userIdentity = userParticipant.userIdentity and still nameComponents is empty. Given that my App requires iCloud, is there a way to get (familyName,givenName)?
2
0
824
Oct ’24
SwiftData ModelConfigurations always sync to iCloud if one of them has iCloud enabled
I'm facing a weird issue with SwiftData. I want to have one database that's local to the device and one that syncs to iCloud. In this example, LTRLink should be synced via iCloud while LTRMetadata should stay on-device only. I've it configured like the following: let schema = Schema([LTRLink.self, LTRMetadata.self]) let cloudkitConfiguration = ModelConfiguration("Remote", schema: schema, url: FileManager.remoteDatabaseFolderURL.appending(path: "Remote.sqlite"), cloudKitDatabase: .private("iCloud.com.xavimoll.abyss3")) let localConfiguration = ModelConfiguration("Local", schema: schema, url: FileManager.localDatabaseFolderURL.appending(path: "Local.sqlite"), cloudKitDatabase: .none) return try ModelContainer(for: schema, configurations: [cloudkitConfiguration, localConfiguration]) For some reason, when I create the iCloud schema, both models end up appearing as records on iCloud. I create the schema like this: let schema = Schema([LTRLink.self, LTRMetadata.self]) let cloudkitConfiguration = ModelConfiguration("Remote", schema: schema, url: FileManager.remoteDatabaseFolderURL.appending(path: "Remote.sqlite"), cloudKitDatabase: .private("iCloud.com.xavimoll.abyss3")) #if DEBUG // Needed to create the schema on iCloud try autoreleasepool { let desc = NSPersistentStoreDescription(url: cloudkitConfiguration.url) let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudkitConfiguration.cloudKitContainerIdentifier!) desc.cloudKitContainerOptions = opts desc.shouldAddStoreAsynchronously = false if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [LTRLink.self]) { let container = NSPersistentCloudKitContainer(name: "Remote", managedObjectModel: mom) container.persistentStoreDescriptions = [desc] container.loadPersistentStores {_, err in if let err { fatalError(err.localizedDescription) } } try container.initializeCloudKitSchema() if let store = container.persistentStoreCoordinator.persistentStores.first { try container.persistentStoreCoordinator.remove(store) } } } #endif let localConfiguration = ModelConfiguration("Local", schema: schema, url: FileManager.localDatabaseFolderURL.appending(path: "Local.sqlite"), cloudKitDatabase: .none) return try ModelContainer(for: schema, configurations: [cloudkitConfiguration, localConfiguration]) The logic to initialize the CloudKit schema follows the documentation found here: https://developer.apple.com/documentation/swiftdata/syncing-model-data-across-a-persons-devices#Initialize-the-CloudKit-development-schema It looks like setting cloudKitDatabase: .none on the init for the ModelConfiguration doesn't do anything, and ends up being synced with iCloud either way. When I go to the iCloud console, I see the following: Does anyone know if there's any workaround that would allow me to have two databases where only one of them syncs to iCloud when using SwiftData?
1
0
618
Oct ’24
Does CloudKit guarantee CKRecord.Reference is always valid?
I'm considering using CloudKit in my app (it doesn't use Core Data) and have read as many materials as I can find. I haven't fully grasped it yet and have a basic question on CKRecord.Reference. Does CloudKit guarantee CKRecord.Reference value is always valid? By valid I mean the target CkRecord pointed by the CKRecord.Reference exists in the database. Let's consider an example. Suppose there are two tables: Account and Transaction: Account Table: AccountNumber Currency Rate ------------- -------- ---- a1 USD 0.03 Transaction Table: TransactionNumber AccountNumber Amount ----------------- ------------- ------ t1 a1 20 Now suppose user does the following: User first deletes account a1 and its associated transactions t1 on device A. The device saves the change to cloud. Then user adds a new transaction t2 to account a1 on device B, before the device receives the change made in step 1 from cloud. Since a1 hasn't been deleted on device B, the operation should succeed locally. The device tries to save the change to cloud too. My questions: Q1) Will device B be able to save the change in step 2 to cloud? I hope it would fail, because otherwise it would lead to inconsistent data. But I find the following in CKModifyRecordsOperation doc (emphasis mine), which implies CloudKit allows invalid reference: During a save operation, CloudKit requires that the target record of the parent reference, if set, exists in the database or is part of the same operation; all other reference fields are exempt from this requirement. (BTW, I think the fact that, when using CloudKit, Core Data requires all relations must be optional also indicates that CloudKit can't guarantee relation is always valid, though I think that is mainly an issue on client side caused by data transfer size. The above example, however, is different in that it's an issue on cloud side - the data on cloud is inconsistent). I also find the following in the document. However, I don't think it helps in the above example, because IIUC CloudKit can only detect conflict when the changes on the same record but the changes in step 1 and step 2 are on different records. Because records can change between the time you fetch them and the time you save them, the save policy determines whether new changes overwrite existing changes. By default, the operation reports an error when there’s a newer version on the server. If the above understanding is correct, however, I don't understand why the same document has the following requirement, which implies CloudKit doesn't allow invalid reference: When creating two new records that have a reference between them, use the same operation to save both records at the same time. Q2) Suppose CloudKit allows invalid reference on cloud side (that is, device B successfully saves the change in step 2 to cloud) , I wonder what's the best practice to deal with it? I think the issue is different from the optional relation requirement in Core Data when using CloudKit, because in that case the data is consistent on cloud side and eventually the client will receive complete data. In the above example, however, the data on cloud is inconsistent so the client has to remedy it somehow (although client has little information helping it). One approach I think of is to avoid the issue in the first place. My idea is to maintain a counter in the database and requires client to increase the counter (it's not Lamport clock. BTW, is it possible to use Lamport clock in this case?) when making any change. This should help CloudKit to detect conflict (though I can't think out a good strategy on how client should deal with it. A simple one is perhaps to prompt user to select one copy). However, this approach effectively uses cloud as a centralized server, which I suspect isn't the typical way how people use CloudKit, and it requires clients to maintain local counter value in various situations. I wonder what's the typical approach? Am I missing something? Thanks for any help.
2
0
909
Oct ’24
Persist app state across reinstalls/multiple devices
So I’m trying to setup an existing app to work with iCloud syncing. The syncing part seems to be working for the most part. When the app is first installed it sets up some data locally. Throughout the life of the app additional data is added through updates. There is a user default setup that stores the current data version, then compares it with the new version. If it’s newer, then loads the additional data. The issue I’ve got is a user can delete the app and reinstall, or install on another device which has that data version as 0, prompting another import even though the data in the cloud is current version, resulting in duplicate data once the sync is done. How can I persist that version data? I’ve seen NSUbiquitousKeyValueStore which seems to be a cloud based version of user defaults, but it says not to rely on it if it’s critical to app functions
0
0
308
Oct ’24
iOS 18 Core Data and CloudKit Sync Issue with NSPersistentCloudKitContainer
After upgrading to iOS 18, my Core Data stack using NSPersistentCloudKitContainer in a shared App Group container stopped syncing correctly. The persistent store configuration, which previously worked in iOS 17, now experiences delayed or missing sync updates between devices. Then the app freezes and writes terminal the same error detail (which I provided) too many times. The debug logs from the CloudKit mirroring delegate (NSCloudKitMirroringDelegate) show repetitive notifications but no updates in persistent history. Additionally, the persistent history tracking key appears unresponsive to local changes, causing transactions to fail in updating or syncing as expected. Key setup details: Core Data is set up within an App Group container using NSPersistentCloudKitContainer. NSPersistentHistoryTrackingKey and NSPersistentStoreRemoteChangeNotificationPostOptionKey options are set to true. Any insights into changes in iOS 18 Core Data or CloudKit handling with NSPersistentCloudKitContainer, especially around history tracking and sync delays, would be greatly appreciated. Thank you. Error Detail file:///private/var/mobile/Containers/Shared/AppGroup/BF95D309-EBE9-485E-B5CE-AA17097F7B60/[AppName]Database.sqlite CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](3123): <NSCloudKitMirroringDelegate: 0x3032b4870>: Observed context save: <NSPersistentStoreCoordinator: 0x302694bd0> - <NSManagedObjectContext: 0x3036b1a00> CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate remoteStoreDidChange:](3166): <NSCloudKitMirroringDelegate: 0x3032b4870>: Observed remote store notification: <NSPersistentStoreCoordinator: 0x302694bd0> - 090C4244-0101-4DEF-90D6-1260570F47A5 - <NSPersistentHistoryToken - { "090C4244-0101-4DEF-90D6-1260570F47A5" = 9; }> - Persistence.swift struct PersistenceController { let container: NSPersistentCloudKitContainer static let shared = PersistenceController() static var preview: PersistenceController = {PersistenceController()}() init() { container = NSPersistentCloudKitContainer(name: "[AppName]") // Configure CloudKit for the default container if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.[CompanyName].[AppName]") { let storeURL = url.appendingPathComponent("[AppName]Database.sqlite") let description = container.persistentStoreDescriptions.first description?.url = storeURL description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) container.persistentStoreDescriptions = [description].compactMap { $0 } } container.loadPersistentStores { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } } container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy } }
0
1
572
Oct ’24
Object deleted in MOC not properly deleted in child MOC
I have two contexts, MAIN and VIEW. I construct an object in MAIN and it appears in VIEW (which I use to display it in the UI). Then I delete the object in MAIN. Because the UI holds a reference to the object in VIEW, VIEW records it as a pending delete (Problem 1). I don't understand why it does this nor can I find this behaviour documented. Docs for deletedObjects say "objects that will be removed from their persistent store during the next save". This has already happened! (Problem 2) Then I rollback the VIEW context, and the object is resurrected. awakeFromInsert is called again. While the object (correctly) does not appear in a freshly executed fetch request, it does appear in the @FetchRequest of the SwiftUI View which is now displaying stale data. I cannot figure out how to get SwiftUI to execute the fetch request again (I know I can force regeneration of the UI, but would like to avoid this). This is self-contained demonstration of the problem that can be run in a Playground. Press Create, then Delete (note console output), then Rollback (note console output, and that element count changes from 0 to 1 in the UI) import CoreData import SwiftUI @objc(TestEntity) class TestEntity : NSManagedObject, Identifiable{ @NSManaged var id : UUID? override func awakeFromInsert() { print("Awake from insert") if id == nil { // Avoid resetting ID when we resurrect the phantom delete self.id = UUID() } super.awakeFromInsert() } class func add(in context: NSManagedObjectContext) -> UUID { let id = UUID() context.performAndWait { let mo = TestEntity(context: context) mo.id = id } return id } class func fetch(in context: NSManagedObjectContext) -> [TestEntity] { let fr = TestEntity.fetchRequest() return try! context.fetch(fr) as! [TestEntity] } } class CoreDataStack { // Main is attached to the store var main : NSManagedObjectContext! // View is a child context of main and used to display the UI var view : NSManagedObjectContext! // Set up a simple entity with an ID attribute func getEntities() -> [NSEntityDescription] { let testEntity = NSEntityDescription() testEntity.managedObjectClassName = "TestEntity" testEntity.name = "TestEntity" let idAttribute = NSAttributeDescription() idAttribute.name = "id" idAttribute.type = .uuid testEntity.properties.append(idAttribute) return [testEntity] } init() { let model = NSManagedObjectModel() model.entities = getEntities() let container = NSPersistentContainer(name: "TestModel", managedObjectModel: model) let description = NSPersistentStoreDescription() description.type = NSInMemoryStoreType container.persistentStoreDescriptions = [description] container.loadPersistentStores { desc, error in if error != nil { fatalError("Failed to set up coredata") } } main = container.viewContext view = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) view.automaticallyMergesChangesFromParent = true view.parent = main } func create() { let entityId = TestEntity.add(in: main) main.performAndWait { try! main.save() } } func delete() { main.performAndWait { if let mo = TestEntity.fetch(in: main).first { main.delete(mo) try! main.save() } } self.view.perform { // We only find that we have a pending delete here if we hold a reference to the object, e.g. in the UI via @FetchRequest if(self.view.deletedObjects.count != 0) { print("!!! view has a pending delete, even though main has saved the delete !!!") } } } func rollback() { self.view.perform { self.view.rollback() // PROBLEM We now have a resurrected object. Note that awakeFromInsert // was called again. } } } import SwiftUI import PlaygroundSupport let stack = CoreDataStack() struct ContentView: View { @FetchRequest(sortDescriptors: []) private var entities: FetchedResults<TestEntity> @State var renderID = UUID() var body: some View { VStack { Text("\(entities.count) elements") Button("Create") { stack.create() } Button("Delete") { stack.delete() } Button("Rollback") { stack.rollback() // PROBLEM After rollback we get the element displaying in // the UI again, even though it isn't present in a freshly // executed fetch request. // The @FetchRequest is picking up the resurrected TestEntity in view // But not actually issuing a fetch. self.renderID = UUID() entities.nsPredicate } }.id(renderID) } } //stack.execute() let view = ContentView() .environment(\.managedObjectContext, stack.view) PlaygroundPage.current.setLiveView(view)
4
0
950
Oct ’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
Core Data boilerplate project causes Fatal Error
I'm using Xcode 16 and SwiftUI targeting iOS 18. I'm new to Core Data, and when I create a new project and select to use Core Data as storage, I get boilerplate code for it. The problem is that when I try to see the preview without any change to the code, I get a Fatal Error: CrashReportError: Fatal Error in Persistence.swift Test crashed due to fatalError in Persistence.swift at line 52. Unresolved error Error Domain=NSSQLiteErrorDomain Code=8 "(null)" UserInfo={NSFilePath=/Users/monni/Library/Developer/Xcode/UserData/Previews/Simulator Devices/D0D98B5B-7E6F-4DC3-B16A-34D6D2958558/data/Containers/Data/Application/A98879A6-46F5-4E29-B2D7-AD294F1EFFD0/Library/Application Support/Test.sqlite, NSSQLiteErrorDomain=8}, ["NSSQLiteErrorDomain": 8, "NSFilePath": /Users/monni/Library/Developer/Xcode/UserData/Previews/Simulator Devices/D0D98B5B-7E6F-4DC3-B16A-34D6D2958558/data/Containers/Data/Application/A98879A6-46F5-4E29-B2D7-AD294F1EFFD0/Library/Application Support/Test.sqlite] When I try to open the SQLite database there are no entities in it. I have also tried xcrun simctl --set previews delete all, but with no luck.
2
1
453
Oct ’24
CKShare Invitation URL sharing
CKShare provides a url that allows others to be invited. It is necessary for a potential participant to have access to this url (otherwise there is no way for them to accept the invitation). An easy solution is to send this url via the Messages application, but this is an extra step for the share owner. I have noticed that Apple's Passwords app somehow sends this url to the invited user within the Passwords app - and I wonder if this is possible with just public Apple apis, or if Apple uses some private api to achieve this.
3
0
921
Oct ’24
iCloud Documents + UIDocumentBrowserViewController
Our app is a document-based app that uses UIDocumentBrowserViewController. We are facing an issue when the user is creating a new document on iOS/iPadOS when in the “Recents” tab (as opposed to the “Browse” tab). Specifically, the document is saved to a hidden ubiquity container. As a result, the user cannot find the file in the document browser. It also does not appear in “Recents”. The expected behaviour would be a folder with our app's icon on it on the user’s iCloud Drive, which contains the files the user creates when in the “Recents” tab. This issue started to happen when we introduced a new feature that uses iCloud Documents with its own ubiquity container. I'm not sure how UIDocumentBrowserViewController handled saving documents to a default location on iCloud Drive before we had the iCloud Documents entitlement enabled. All I know is that there were no issues. How to recreate the issue: Create a document-based app with UIDocumentBrowserViewController. Run the app and create a document while in the recents tab with iCloud enabled. The document will be stored to a folder on iCloud. Now, enable iCloud Documents and specify a ubiquity container. Then, try to create documents in the Recents tab. The location in which the documents are created cannot be navigated to.
5
0
1.2k
Nov ’24
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