Since running on iOS 14b1, I'm getting this in my log (I have Core Data logging enabled):
error: Store opened without NSPersistentHistoryTrackingKey but previously had been opened with NSPersistentHistoryTrackingKey - Forcing into Read Only mode store at 'file:///private/var/mobile/Containers/Shared/AppGroup/415B75A6-92C3-45FE-BE13-7D48D35909AF/StoreFile.sqlite' 
As far as I can tell, it's impossible to open my store without that key set - it's in the init() of my NSPersistentContainer subclass, before anyone calls it to load stores.
Any ideas?
                    
                  
                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
Created
                    
                      One question I often see on DevForums and in my day DTS job is if a Core Data object managed by NSPersistentCloudKitContainer can be shared with other iCloud users. 
The answer is yes but you need to do it using CloudKit API directly because NSPersistentCloudKitContainer doesn’t support CloudKit shared database (CKContainer.sharedCloudDatabase) today.
Assuming you have a Core Data object, let’s say a document, that you’d like to collaborate with your colleagues:
 You are the document owner and can use NSPersistentCloudKitContainer to fully manages the document and synchronize it across your devices.
 You can grab a CloudKit record associated with your document from NSPersistentCloudKitContainer using record(for:) or recordID(for:), and share it to your colleagues using UICloudSharingController. See our Sharing CloudKit Data with Other iCloud Users - https://developer.apple.com/documentation/cloudkit/sharing_cloudkit_data_with_other_icloud_users sample for how to share a CloudKit record.
 After accepting the sharing, your colleague, as a participant, can view or edit the shared document. The document resides in the participant’s CloudKit shared database and you have to manage it with your own code. 
 When your colleague edits and saves the shared document, the changes go to the owner’s private database, and eventually synchronize to NSPersistentCloudKitContainer on the owner side. 
As you can see, you need to implement #2 and #3 with your own code because NSPersistentCloudKitContainer can’t manage the data in the participant's shared database. If you have any difficulty after going through the above sample code, you can contact Apple’s DTS for help.
                    
                  
                
                    
                      My use case is the following:
Every user of my app can create as an owner a set of items. 
These items are private until the owner invites other users to share all of them as participant.
The participants can modify the shared items and/or add other items.
So, sharing is not done related to individual items, but to all items of an owner.
I want to use CoreData & CloudKit to have local copies of private and shared items.
To my understanding, CoreData & CloudKit puts all mirrored items in a special zone „com.apple.coredata.cloudkit.zone“.
So, this zone should be shared, i.e. all items in it.
In the video it is said that NSPersistentCloudKitContainer uses Record Zone Sharing optionally in contrast to hierarchically record sharing using a root record.
But how is this done?
Maybe I can declare zone „com.apple.coredata.cloudkit.zone“ as a shared zone?
                    
                  
                
              
                
              
              
                
                Topic:
                  
	
		App & System Services
  	
                
                
                SubTopic:
                  
                    
	
		iCloud & Data
		
  	
                  
                
              
              
                Tags:
              
              
  
  
    
      
      
      
        
          
            Cloud and Local Storage
          
        
        
      
      
    
      
      
      
        
          
            UI Frameworks
          
        
        
      
      
    
      
      
      
        
          
            wwdc21-10015
          
        
        
      
      
    
  
  
              
                
                
              
            
          
                    
                      Background
I have an established app in the App Store which has been using NSPersistentCloudkitContainer since iOS 13 without any issues.
I've been running my app normally on an iOS device running the iOS 15 betas, mainly to see problems arise before my users see them.
Ever since iOS 15 (beta 4) my app has failed to sync changes - no matter how small the change. An upload 'starts' but never completes. After a minute or so the app quits to the Home Screen and no useful information can be gleaned from crash reports. Until now I've had no idea what's going on.
Possible Bug in the API?
I've managed to replicate this behaviour on the simulator and on another device when building my app with Xcode 13 (beta 5) on iOS 15 (beta 5).
It appears that NSPersistentCloudkitContainer has a memory leak and keeps ramping up the RAM consumption (and CPU at 100%) until the operating system kills the app. No code of mine is running.
I'm not really an expert on these things and I tried to use Instruments to see if that would show me anything. It appears to be related to NSCloudkitMirroringDelegate getting 'stuck' somehow but I have no idea what to do with this information.
My Core Data database is not tiny, but not massive by any means and NSPersistentCloudkitContainer has had no problems syncing to iCloud prior to iOS 15 (beta 4).
If I restore my App Data (from an external backup file - 700MB with lots of many-many, many-one relationships, ckAssets, etc.) the data all gets added to Core Data without an issue at all. The console log (see below) then shows that a sync is created, scheduled & then started... but no data is uploaded.
At this point the memory consumption starts and all I see is 'backgroundTask' warnings appear (only related to CloudKit) with no code of mine running.
CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitExporter analyzeHistoryInStore:withManagedObjectContext:error:](501): <PFCloudKitExporter: 0x600000301450>: Exporting changes since (0): <NSPersistentHistoryToken - {
    "4B90A437-3D96-4AC9-A27A-E0F633CE5D9D" = 906;
}>
CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitExportContext processAnalyzedHistoryInStore:inManagedObjectContext:error:]_block_invoke_3(251): Finished processing analyzed history with 29501 metadata objects to create, 0 deleted rows without metadata.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _scheduleAutomatedExportWithLabel:activity:completionHandler:](2800): <NSCloudKitMirroringDelegate: 0x6000015515c0> - Beginning automated export - ExportActivity:
<CKSchedulerActivity: 0x60000032c500; containerID=<CKContainerID: 0x600002ed3240; containerIdentifier=iCloud.com.nitramluap.Somnus, containerEnvironment="Sandbox">, identifier=com.apple.coredata.cloudkit.activity.export.4B90A437-3D96-4AC9-A27A-E0F633CE5D9D, priority=2, xpcActivityCriteriaOverrides={ Priority=Utility }>
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate executeMirroringRequest:error:](765): <NSCloudKitMirroringDelegate: 0x6000015515c0>: Asked to execute request: <NSCloudKitMirroringExportRequest: 0x600002ed2a30> CBE1852D-7793-46B6-8314-A681D2038B38
2021-08-13 08:41:01.518422+1000 Somnus[11058:671570] [BackgroundTask] Background Task 68 ("CoreData: CloudKit Export"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
2021-08-13 08:41:03.519455+1000 Somnus[11058:671570] [BackgroundTask] Background Task 154 ("CoreData: CloudKit Scheduling"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
Just wondering if anyone else is having a similar issue? It never had a problem syncing an initial database restore prior to iOS 15 (beta 4) and the problems started right after installing iOS 15 (beta 4).
I've submitted this to Apple Feedback and am awaiting a response (FB9412346). If this is unfixable I'm in real trouble (and my users are going to be livid).
Thanks in advance!
                    
                  
                
                    
                      I'm using NSPersistentCloudKitContainer with Core Data and I receive errors because my iCloud space is full. The errors printed are the following: <CKError 0x280df8e40: "Quota Exceeded" (25/2035); server message = "Quota exceeded"; op = 61846C533467A5DF; uuid = 6A144513-033F-42C2-9E27-693548EF2150; Retry after 342.0 seconds>.
I want to inform the user about this issue, but I can't find a way to access the details of the error. I'm listening to NSPersistentCloudKitContainer.eventChangedNotification, I receive a error of type .partialFailure. But when I want to access the underlying errors, the partialErrorsByItemID property on the error is nil.
How can I access this Quota Exceeded error?
import Foundation
import CloudKit
import Combine
import CoreData
class SyncMonitor {
    fileprivate var subscriptions = Set<AnyCancellable>()
    init() {
        NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification)
            .sink { notification in
                if let cloudEvent = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey] as? NSPersistentCloudKitContainer.Event {
                    guard let ckerror = cloudEvent.error as? CKError else {
                        return
                    }
                
                    print("Error: \(ckerror.localizedDescription)")
                    if ckerror.code == .partialFailure {
                        guard let errors = ckerror.partialErrorsByItemID else {
                            return
                        }
                    
                        for (_, error) in errors {
                            if let currentError = error as? CKError {
                                print(currentError.localizedDescription)
                            }
                        }
                    }
                
                }
            } // end of sink
            .store(in: &subscriptions)
    }
}
                    
                  
                
                    
                      Hi All,
I  work on a cross platform app, iOS/macOS.
All devises on iOS could synchronize data from Coredata : I create a client, I see him an all iOS devices.
But when I test on macOs (with TestFlight) the Mac app could not get any information from iOs devices.
On Mac,  cloud drive is working because I could download and upload documents and share it between all devices, so the account is working but with my App on MacOS, there is no synchronisation.
idea????
                    
                  
                
                    
                      When my app starts it loads data (of vehicle models, manufacturers, ...) from JSON files into CoreData.  This content is static.
Some CoreData entities have fields that can be set by the user, for example an isFavorite boolean field.
How do I tell CloudKit that my CoreData objects are 'static' and must not be duplicated on other devices (that will also load it from JSON files).
In other words, how can I make sure that the CloudKit knows that the record created from JSON for vehicle model XYZ on one device is the same record that was created from JSON on any other device?
I'm using NSPersistentCloudKitContainer.
                    
                  
                
                    
                      anyone getting the following error with CloudKit+CoreData on iOS16 RC?
delete/resintall app, delete user CloudKit data and reset of environment don't fix.
[error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _requestAbortedNotInitialized:](2044): <NSCloudKitMirroringDelegate: 0x2816f89a0> - Never successfully initialized and cannot execute request '<NSCloudKitMirroringImportRequest: 0x283abfa00> 41E6B8D6-08C7-4C73-A718-71291DFA67E4' due to error: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)}
                    
                  
                
                    
                      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'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.
                    
                  
                
                    
                      The NSPersistentCloudKitContainer  synchronization between core data and
iCloud was working fine with phone 15.1. Connected a new iPhone iOS 15.5, it gives  error:
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](2504): <NSCloudKitMirroringDelegate: 0x28198c000>: Observed context save: <NSPersistentStoreCoordinator: 0x2809c9420> - <NSManagedObjectContext: 0x2819ad520>
2022-12-05 13:32:28.377000-0600 r2nr[340:6373] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error:
Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)}
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error:
Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)}
I go back and try with my old iPhone iOS 15.1, gives same error.
                    
                  
                
                    
                      I have an image field on a Core Data entity with "Allows External Storage" enabled. When I delete a record, the external binary data file remains on disk. How can I ensure that all externally stored data is deleted along with the record?
                    
                  
                
                    
                      Hi all,
Has anyone stumbled upon the SwiftData equivalent of @SectionedFetchRequest? Is there a way to do it with @Query? I'll keep going through the documentation but if anyone has an answer, it would be much appreciated!!
Thank you.
                    
                  
                
                    
                      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?
                    
                  
                
                    
                      I've been testing out SwiftData but haven't bee able to get ModelContext notifications working. I've tried both an objc observer and for await patterns but it never fires. If I listen for the older nsmanagedcontext notifications they are firing, but I am hoping that the new ones give an ID instead of an objectId. Has anyone got these working?
Attempt 1:
class NotificationObserver {
    init() {
        let didSaveNotification = ModelContext.didSave
        NotificationCenter.default.addObserver(self, selector: #selector(didSave(_:)),
                                               name: didSaveNotification, object: nil)
    }
    @objc func didSave(_ notification: Notification) {
        print(notification.name)
    }
}
Attempt 2:
class NotificationObserver {
    init() {
        let didSaveNotification = ModelContext.didSave
        Task {
            for await note in NotificationCenter.default.notifications(named: didSaveNotification) {
                print(note)
            }
        }
    }    
}
                    
                  
                
                    
                      As far as I can tell, there’s no equivalent to Core Data’s NSFetchedResultsController in SwiftData. It would be very helpful to have a way to respond to sets of changes in a ModelContext outside of a SwiftUI view. For instance, this is very helpful when using a Model-View-ViewModel architecture.
The @Query property wrapper is great for use in a SwiftUI view, but sometimes it’s helpful to process data outside of the view itself. The fetch() method on ModelContext is helpful for one-time operations, but as far as I can't tell it doesn't address receiving changes on an ongoing basis.
Am I missing some equivalent for this use case?
Also filed as feedback FB12288916
                    
                  
                
                    
                      The 'unique' attribute is a really nice feature, BUT. In some of my apps, the unique identifier for an object is a combination of multiple attributes. (Example: a book title is not unique, but a combination of book title and author list is.)
How do I model this with SwiftData? I cannot use @Attribute(.unique) on either the title OR the author list, but I want SwiftData to provide the same "insert or update" logic.
Is this possible?
                    
                  
                
                    
                      I have created an actor for the ModelContainer, in order to perform a data load when starting the app in the background. For this I have conformed to the ModelActor protocol and created the necessary elements, even preparing for test data.
Then I create a function of type async throws to perform the database loading processes and everything works fine, in that the data is loaded and when loaded it is displayed reactively.
actor Container: ModelActor {
    nonisolated let modelContainer: ModelContainer
    nonisolated let modelExecutor: ModelExecutor
    static let modelContainer: ModelContainer = {
        do {
            return try ModelContainer(for: Empleados.self)
        } catch {
            fatalError()
        }
    }()
    
    let context: ModelContext
    
    init(container: ModelContainer = Container.modelContainer) {
        self.modelContainer = container
        let context = ModelContext(modelContainer)
        self.modelExecutor = DefaultSerialModelExecutor(modelContext: context)
        self.context = context
        Task {
            do {
                try await loadData()
            } catch {
                print("Error en la carga \(error)")
            }
        }
    }
}
The problem is that, in spite of doing the load inside a Task and that there is no problem, when starting the app it stops responding the UI while loading to the user interactions. Which gives me to understand that actually the task that should be in a background thread is running somehow over the MainActor.
As I have my own API that will provide the information to my app and refresh it at each startup or even send them in Batch when the internet connection is lost and comes back, I don't want the user to be continuously noticing that the app stops because it is performing a heavy process that is not really running in the background.
Tested and compiled on Xcode 15 beta 7.
I made a Feedback for this: FB13038621.
Thanks
Julio César
                    
                  
                
                    
                      Problem
The following code doesn't work:
let predicate = #Predicate<Car> { car in
   car.size == size //This doesn't work
}
Console Error
Query encountered an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.unsupportedPredicate)
Root cause
Size is an enum, #Predicate works with other type such as String however doesn't work with enum
Enum value is saved however is not filtered by #Predicate
Environment
Xcode: 15.0 (15A240d) - App Store
macOS: 14.0 (23A339) - Release Candidate
Steps to reproduce
Run the app on iOS 17 or macOS Sonoma
Press the Add button
Notice that the list remains empty
Expected behaviour
List should show the newly created small car
Actual behaviour
List remains empty inspite of successfully creating the small car.
Feedback
FB13194334
Code
Size
enum Size: String, Codable {
    case small
    case medium
    case large
}
Car
import SwiftData
@Model
class Car {
    let id: UUID
    let name: String
    let size: Size
    
    init(
        id: UUID,
        name: String,
        size: Size
    ) {
        self.id = id
        self.name = name
        self.size = size
    }
}
ContentView
struct ContentView: View {
    var body: some View {
        NavigationStack {
            CarList(size: .small)
        }
    }
CarList
import SwiftUI
import SwiftData
struct CarList: View {
    let size: Size
    
    @Environment(\.modelContext)
    private var modelContext
    @Query
    private var cars: [Car]
    
    init(size: Size) {
        self.size = size
        let predicate = #Predicate<Car> { car in
            car.size == size //This doesn't work
        }
        _cars = Query(filter: predicate, sort: \.name)
    }
    
    var body: some View {
        List(cars) { car in
            VStack(alignment: .leading) {
                Text(car.name)
                Text("\(car.size.rawValue)")
                Text(car.id.uuidString)
                    .font(.footnote)
            }
        }
        .toolbar {
            Button("Add") {
                createCar()
            }
        }
    }
    
    private func createCar() {
        let name = "aaa"
        let car = Car(
            id: UUID(),
            name: name,
            size: size
        )
        modelContext.insert(car)
    }
}
                    
                  
                
                    
                      Hi all,
has anybody found the trick how to get SwiftData working with SpotLight Search?
Setting the attribute "spotlight" in the Model definition seems to do nothing at all,  as pointed out by Paul Hudson in his new book as well
(https://www.hackingwithswift.com/quick-start/swiftdata/how-to-index-swiftdata-objects-in-spotlight)
Thanks a lot!