TLDR: How can I listen to changes in SwiftData and share the data via WatchConnectivity?
I am developing an app for the Apple Watch where the iPhone can act as a remote for the Watch.
The App on the Watch should work independently from iPhone. The user can create elements on the Watch and start the action associated with the element. The iPhone user can see the elements created on the Watch and start the action on the Watch from the iPhone (if possible I want to add the functionality to let the user update the elements on both devices, but that's not a priority atm).
I tried to get it to work with CloudKit and SwiftData, but somehow I couldn't get CloudKit to initialize correctly. After further research, I reconned that using WatchConnectivity and ApplicationContext should be a suitable approach.
To communicate with the iPhone App, I created a singleton class that manages the communication. Now I want this class to listen to the changes in SwiftData to send the elements to the iPhone, but I don't know how I can get access to the ModelContext in the Communicator class. I read that passing the value from the initializer of a view is not good practice and it didn't work for me.
What would be a suitable way to achieve the desired behavior of my app? Any help and feedback is appreciated. TIA
CloudKit
RSS for tagStore structured app and user data in iCloud containers that can be shared by all users of your app using CloudKit.
Posts under CloudKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
We're doing some disaster recovery management / risk management and a point-of-failure for our app is if we lose access to our bundle id.
From my understanding, secure keychain items are scoped to your bundle ID as well as iCloud files stored under the app with 'hidden' scope.
Losing our bundle ID is a scenario we want to eliminate completely from our threat/disaster modelling.
Is this a realistic concern we should have?
Is there any tool to automatically migrate data & data structure from Google Firebase to CloudKit?
So I am trying to sync only some of my Models with iCloud and others kept locally in the default.store. I am having a world of issues so before I start looking for the needle in my haystack. I would like to ask this forum, is my approach one that should work as desired or is my code obviously why things are not working? All my Models have default values and relationships where needed are optionals. iCloud is working but my issue arises when i try to exclude some models. So I want to sync "modelsForCloudSyncing" but not "modelNotForCloudSyncing" In advance thank you
var avoidCloudSyncModelContainer : ModelContainer = {
let modelNotForCloudSyncing = Schema([NoCloudSyncModel.self])
let modelConfigForNoCloudSync = ModelConfiguration(schema: modelNotForCloudSyncing, cloudKitDatabase: .none)
let modelsForCloudSyncing = Schema([CloudSyncModelA.self, CloudSyncModelB.self, CloudSyncModelC.self])
let modelConfigForCloudSync = ModelConfiguration(schema: modelsForCloudSyncing, cloudKitDatabase: .automatic)
do {
return try ModelContainer(for: NoCloudSyncModel.self, CloudSyncModelA.self, CloudSyncModelB.self, CloudSyncModelC.self, configurations: modelConfigForNoCloudSync, modelConfigForCloudSync)
}
catch { fatalError("Could not create ModelContainer: \(error)") }
}()
...
{
ContentView()
}.modelContainer(avoidCloudSyncModelContainer)
I'm working on migrating my app from using CoreData to SwiftData. The swift data code generated by Xcode works correctly for the iOS and Mac Catalyst targets but it is causing a crash for the WatchOS target.
It gives me this message **Fatal error: Application must register a ValueTransformer for NSSecureUnarchiveFromDataTransformer **
This attribute is the only one with a .transformable option.
@Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformer"))
public var linkedEntities: [UUID] = []
Changing the string NSSecureUnarchiveFromDataTransformer to NSValueTransformerName.secureUnarchiveFromDataTransformerName.rawValue causes a generic crash with no error message.
The app has CloudKit integration as well (not sure if relevant).
Does anyone have a similar issue and can help me on what to do here?
I have made an app to test flight, and I am using Push Notifications Console by apple, and all I need it how to get the hexadecimal bytes that identify the recipient's device. (Device Token) to be able to send push notifications. I just want to send it to all users at the same time.
I'm testing disabling iCloud for my app (https://support.apple.com/en-gb/HT207689) and it's disabled in my main app but when I use the share extension it's always enabled. I would think that disabling iCloud would disable it for all extensions you might have in your app.
Is there no way to disable iCloud for an extension only for main app?
Hello,
I have a couple of questions about the CloudKit public database:
Is it possible to control what authenticated users can write to the database on the server side? I know I could write logic in my iOS app to prevent to prevent certain actions, like uploading more data than I want to allow, but traditionally one would write server-side checks too. Even if I don't use CloudKit JS, it still seems like a malicious user could intercept network traffic and interact directly with iCloud to bypass any validations I've included in my app.
Is it possible to block a user from using my app and interacting with CloudKit entirely? Along the same lines as question 1, I may want to block a malicious user from interacting with my public database, particularly writing to it.
Is it common practice to write configuration settings to the public database as an administrative user and to have the app look for these known records? For example, I could add records to a configuration zone via the iCloud dashboard and have my app read them at startup to do things like enable/disable signups.
Thanks for any help and guidance on these issues!
Starting only recently, cloudSharingControllerDidSaveShare: stopped firing with no code changes on my end.
Is anyone else experiencing this same issue?
I found that the main application and widget NSUbiquitousKeyValueStore data is completely independent?
(I signed in to the same iCloud account, the same AppGroup, the same iCloud Containers for the app and widget, and Key-value Storage was checked.)
But when I get on the widget and modify NSUbiquitousKeyValueStore data, find the Key to the value of the same, such as in the screenshot, the main application of 'gemstone' value is 24, But the widget's value is still 0.
I thought it was a synchronization problem, but using NSUbiquitousKeyValueStore.default.synchronize() or restart the App didn't solve the problem
... “Add Image”function can't used, this is the Logs:
Main App Logs:
---ubiquitousKeyValueStoreDidChange
---Change reason: 0
---The key 'experience' was updated to value '-28'
---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x280098960>(
experience
)
, AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0]
---ubiquitousKeyValueStoreDidChange
---Change reason: 0
---The key 'gemstone' was updated to value '24'
---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x280081c70>(
gemstone
)
widget Logs:
--- widget health: 0, level: 0, experience: 0
---ubiquitousKeyValueStoreDidChange
---Change reason: 0
---The key 'experience' was updated to value '2'
---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0, AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x159e752f0>(
experience
)
]
--- widget health: 0, level: 0, experience: 2
---ubiquitousKeyValueStoreDidChange
---Change reason: 0
---The key 'gemstone' was updated to value '2'
---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0, AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x15bb0cd80>(
gemstone
)
]
I've encountered a significant sync issue with watchOS 10 RC on every device combination I've tested, running both iOS 17 and watchOS 10. I'm curious if others have noticed a similar problem.
Context:
Standalone watchOS app developed in SwiftUI with a companion iOS app.
Both apps use NSPersistentCloudKitContainer for bi-directional CloudKit CoreData Sync between the iOS app and watch.
Previously, this sync mechanism was near instant in the foreground and took max 1-2 minutes in the background
NSPersistentCloudKitContainer has been reliable since the app was first developed in the watchOS 6/iOS 13 era.
Issue:
In watchOS 10 RC, sync can take hours--and doesn't even occur when the app is in the foreground.
Sync only reliably happens when the watch is placed on the charger, seemingly only if the charge is over 50%.
Once taken off the charger, the watch will continue push and receive CoreData changes briefly before becoming unresponsive to sync again.
Additional Info:
The problem persists even when recompiled with the latest Xcode RC.
It's problem is consistent in both production and development CloudKit environments.
The CloudKit log shows no watch activity upon CoreData object updates, until placed on the charger (with over 50% charge). The sync starts in the background while the watch is charging.
The iOS app, however, reflects immediate activity in the CloudKit log after a CoreData change from the device and reacts promptly to pushes when they eventually occur from the watch.
The NSPersistentCloudKitContainer code hasn't changed since it was implemented.
Background modes for remote notifications are set correctly, and when sync finally happens, it's accurate.
I'm stumped. Perhaps there's a new watchOS 10 setting affecting CloudKit sync QoS? Or could this be a known watchOS 10 RC bug?
I’m looking for code samples (if it’s possible) for de-duplicating the public database. I have seen code samples on how to de-duplicate the private database, but I haven’t seen anything regarding the public database.
The crash is at
do {
retval = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
When I first set it up, it complained (at run-time) about a lot of issues, mainly items not being optional and I apparently had a couple of @Attribute(.unique)s left. After I got rid of all of those, however, I get the crash there.
I assume this is an obvious thing that I am doing wrong, but I can't figure it out.
Hello,
I've created multiple Entity in CoreData, that has a relationship to one another. However, I'm unable to create @discardableResult to use in SwiftUI preview.
/// Entity data for use with canvas previews.
static var preview: Entity1 {
let entities1 = Entity1.makePreviews(count: 1)
return entities1[0]
}
@discardableResult
static func makePreviews(count: Int) -> [Entity1] {
var contents = [Entity1]()
let viewContext = PersistenceController.preview.container.viewContext
let persistenceController = PersistenceController.shared
for index in 0..<count {
let entities1 = Entity1(context: viewContext)
entities1.id = UUID()
entities1.title = "Amazing day!"
let photo = Photo(context: viewContext)
let imageData = UIImage(named: "Golden Temple")?.jpegData(compressionQuality: 1) ?? Data()
photo.linkedToJournal = journal
let thumbnail = Thumbnail(context: viewContext)
let thumbnailData = persistenceController.thumbnail(with: imageData)?.jpegData(compressionQuality: 1)
thumbnail.data = thumbnailData
thumbnail.photo = photo
let photoDataObject = PhotoData(context: viewContext)
photoDataObject.data = imageData
photoDataObject.photo = photo
contents.append(entities1)
}
return contents
}
You may also try to use the sample code from https://developer.apple.com/documentation/coredata/sharing_core_data_objects_between_icloud_users to build a SwiftUI Preview.
Appreciate if you could suggest how to build a SwiftUI preview as it saves a lot of development effort and time. Thank you very much!
Hello
Can anyone tell me what the current limits/pricing is for the public database in Cloudkit.
A lot of the information online is out of date and I can't seem to find any up to date information. I believe there used to be a calculator and I also think that limits expanded with number of active users.
Any links or info would be great thanks.
Hello, I'm running into an odd error.
I'm trying to add a composite attribute called period to a Core Data Entity named Report, but I'm getting a compile-time error that points to my xcdatamodel file:
Report.period cannot use an attribute type of "Composite".
In my model configuration I have "Used with CloudKit" box checked. If I uncheck this box, the error goes away and everything builds fine. But the documentation for NSCompositeAttributeDescription says:
You may use composite attributes anywhere you use standard attributes, including lightweight migrations and CloudKit, through NSPersistentCloudKitContainer.
So it seems like I should be able to use composite attributes in Core Data with CloudKit syncing enabled.
What am I missing here? Is this a bug, or am I doing something wrong?
I'm using Xcode 14 beta 4, on macOS Monterey 12.5, developing a Mac app that's using CoreData CloudKit sync — with my context being configured with two configurations (one for a local cache and one data synced via CloudKit).
An issue recently appeared where the app crashes soon after start-up with this message:
[threadmgrsupport] _TSGetMainThread_block_invoke:Main thread potentially initialized incorrectly, cf <rdar://problem/67741850>
And this stack trace:
Thread 1 Queue : com.apple.main-thread (serial)
#0 0x000000018b86b5e8 in ___NSAssertMainEventQueueIsCurrentEventQueue_block_invoke ()
#1 0x0000000105b563a8 in _dispatch_client_callout ()
#2 0x0000000105b58300 in _dispatch_once_callout ()
#3 0x000000018b86a2dc in _DPSNextEvent ()
#4 0x000000018b868e14 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#5 0x000000018b85afe0 in -[NSApplication run] ()
#6 0x000000018b82c6fc in NSApplicationMain ()
#7 0x00000001ae281e98 in specialized runApp(_:) ()
#8 0x00000001aee10588 in runApp<τ_0_0>(_:) ()
#9 0x00000001ae88626c in static App.main() ()
Things work again, if I disable the CloudKit sync by not setting cloudKitContainerOptions on my "Cloud" configuration. Similarly, it works on first install, but reappears on subsequent runs. The code is in a package that's shared with an iOS version of the app, which has no such issues.
I also tried going back to previous commits that worked before, and it works again until at some point it stops working again for the same commits. So it doesn't seem to be caused directly by my code, but rather by something that the CloudKit sync is doing.
Any help would be much appreciated.
Hi,
our app is down since a few hours as we can not fetch data from iCloud
CKErrorDescription = "Request failed with http status code 503";
CKHTTPStatus = 503;
CKRetryAfter = 60;
NSDebugDescription = "CKInternalErrorDomain: 2022";
NSLocalizedDescription = "Request failed with http status code 503";
NSUnderlyingError = "<CKError 0x2806784e0: "Service Unavailable" (2022); "Request failed with http status code 503"; uuid = UID; Retry after 60.0 seconds>";
RequestUUID = "UID";
}
came out of nowhere.
I have deleted the app and try to run the Xcode project again. How can I remove this error ?
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=134020 "The model configuration used to open the store is incompatible with the one that was used to create the store." UserInfo={NSAffectedObjectsErrorKey=<NSManagedObject: 0x6000021c5310>
In order to load your data into the production environment in Apple CloudKit, follow the steps below:
Deploy Your Schema:
Initially, deploy your schema to the production environment using the recommended approach provided by Apple.
Prepare for TestFlight:
Retain all the codes and views utilized previously for uploading data to the development environment.
Deploy your app to TestFlight.
TestFlight Approval and Data Transition:
Upon receiving approval and ensuring the functionality on TestFlight, the same codes and views that were used to upload data to the CloudKit records in the development environment will now point to the production environment.
Consequently, all the data will be uploaded to the production environment, facilitating a smooth transition.
Post this process, your app on TestFlight will interact with the data in the production environment of CloudKit, ensuring consistency and enabling effective testing.
This method ensures a seamless transition of data from the development environment to the production environment, aligning with the operational flow of CloudKit and TestFlight.