I'm a first time developer for Swift, (getting on a bit!) but after programming in VB back in the late 90s I wanted to write an app for iPhone. I think I might have gone about it the wrong way, but I've got an app that works great on my iPhone or works great on my iPad. It saves the data persistently on device, but, no matter how much I try, what I read and even resorting to AI (ChatGPT & Gemini) I still can't get it to save the data on iCloud to synchronise between the two and work across the devices. I think it must be something pretty fundamental I'm doing (or more likely not doing) that is causing the issue.
I'm setting up my signing and capabilities as per the available instructions but I always get a fatal error. I think it might be something to do with making fields optional, but at this point I'm second guessing myself and feeling a complete failure. Any advice or pointers would be really gratefully appreciated. I like my app and would like eventually to get it on the App Store but at this point in time I feel it should be on the failed projects heap!
I've even tried a new Xcode project for iOS and asking it to use SwiftData and CloudKit - the default project should work - right? But it absolutely doesn't for me. Please send help!!
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
I have multiple app ids that are registered with Push Notification, however they do not hsow up in the Push Notification Console for testing.
This started on April 4.
System status says it's fixed, but I'm still having issues
I've noticed that SwiftData's @Relationship seems to potentially cause application crashes.
The crash error is shown in the image.
Since this crash appears to be random and I cannot reproduce it under specific circumstances, I can only temporarily highlight that this issue seems to exist.
@Model final class TrainInfo {
@Relationship(deleteRule: .cascade, inverse: \StopStation.trainInfo)
var stations: [StopStation]?
}
@Model final class StopStation {
@Relationship
var trainInfo: TrainInfo?
}
/// some View
var origin: StopStationDisplayable? {
if let train = train as? TrainInfo {
return train.stations?.first(where: { $0.isOrigin }) ?? train.stations?.first(where: { $0.isStarting })
}
return nil
}
// Some other function or property
func someFunction() {
if let origin, let destination {
// Function implementation
}
}
问题描述:
环境:
Xcode 版本: 16.3
*macOS 版本: 15.4
项目类型: SwiftUI App with SwiftData
问题摘要:
当在 Xcode 项目的 "Signing & Capabilities" 中为启用了 iCloud 能力的应用关联一个具体的 iCloud Container 时,即使代码中并未显式启用 CloudKit 同步(例如,未在 ModelConfiguration 中设置 cloudKitDatabase),SwiftData 的 ModelContainer 在应用启动初始化时也会立即失败并导致崩溃。如果仅启用 iCloud 能力但不选择任何 Container,应用可以正常启动。此问题在使用空的 Schema([]) 进行测试时依然稳定复现。
复现步骤 (使用最小复现项目 - MRE):
使用 Xcode 16.3 创建一个新的 SwiftUI App 项目 (例如,命名为 CloudKitCrashTest)。
在创建时不要勾选 "Host in CloudKit",或者,如果勾选了,先确保后续步骤覆盖相关设置。Storage 选择 None 或 SwiftData 均可复现。
修改 CloudKitCrashTestApp.swift 文件,添加 SwiftData 导入和基本的 ModelContainer 初始化逻辑。关键代码如下:
import SwiftUI
import SwiftData
@main
struct CloudKitCrashTestApp: App {
let sharedModelContainer: ModelContainer
init() {
// 使用空 Schema 进行诊断
let schema = Schema([])
// *不* 指定 cloudKitDatabase
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
sharedModelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration])
print("ModelContainer created successfully.")
} catch {
// 在关联 Container 后,会在此处崩溃
fatalError("Could not create ModelContainer: \(error)")
}
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(sharedModelContainer)
}
}
}
// ... ContentView 定义 ...
进入项目的 Signing & Capabilities 标签页。
点击 + Capability 添加 iCloud。
在 iCloud 服务中,勾选 CloudKit。
此时,不要在 Containers 部分选择任何容器。
运行应用: 应用应该能够成功启动,并在控制台打印 "ModelContainer created successfully."。
停止应用。
回到 Signing & Capabilities -> iCloud -> Containers。
点击 + 添加一个新的自定义容器,或选择 Xcode 默认建议的容器。确保一个容器 ID 被明确选中。
再次运行应用: 应用现在会在启动时立即崩溃,fatalError 被触发。
预期结果:
即使在 Signing & Capabilities 中关联了 iCloud Container,应用也应该能够成功初始化 ModelContainer(尤其是当代码中未使用 cloudKitDatabase 或使用空 Schema 时),不应崩溃。
实际结果:
应用在 ModelContainer 初始化时崩溃,抛出 fatalError,错误信息为:
Could not create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil)
补充说明:
此问题在 iPhone 模拟器上稳定复现。
尝试清理构建文件夹 (Clean Build Folder)、删除派生数据 (Derived Data) 未能解决问题。
使用 Xcode 模板创建项目(勾选 "Host in CloudKit")并在之后手动取消选择 Container 可以运行,但一旦重新选择 Container 就会崩溃,现象一致。
这表明问题与 ModelContainer 初始化过程在检测到项目关联了具体 iCloud Container 标识符(可能涉及读取 .entitlements 文件或准备相关环境)时发生的内部错误有关,而不是由于实际的 CloudKit 同步代码或模型定义。
影响:
此 Bug 阻止了在当前的 Xcode 和 macOS 环境下开发和测试任何需要关联 iCloud Container 的 SwiftData 应用。
There's some logic in my app that first checks to see if a specific CloudKit record zone exists. If it doesn't, it creates the zone, and then my application continues on with its work.
The way I've implemented this right now is by catching the zoneNotFound error when I call CKDatabase#recordZone(for:) (docs) and creating the zone when that happens:
do {
try await db.recordZone(for: zoneID)
} catch let ckError as CKError
where [.zoneNotFound, .userDeletedZone].contains(ckError.code)
{
// createZone is a helper function
try await createZone(zoneID: zoneID, context: context)
}
This works great, but every time I do this, an error is logged in CloudKit Console, which creates a lot of noise and makes it harder to see real errors.
Is there a way to do this without explicitly triggering a CloudKit error?
I just found CKDatabase#recordZones(for:) (docs), which seems like it returns an empty array instead of throwing an error if the zone doesn't exist.
Will calling that and looking for a non-empty array work just as well, but without logging lots of errors in the console?
My newly released App Snapshot-Chess-Move, #1592848671, is not creating a public database of chess moves as I expect. What steps do I need to do inorder for my App to be using a public database. It appears as if each of my iOS devices, iPhone, iPad and Mac mini each have a private database of chess moves. When I change my data on the iPad, I expect the new data to appear (with slight delays) on the Mac.. I do not know what to do next. Please help me. This was working in Development mode but not in Production when I submitted my App for release.
UPDATE:
The cloud data is copied locally to a @Quary variable and updated by using .insert, .delete and .save commands. So, I deleted and re-downloaded my apps on each device, iPad, iPhone, and Mac and obtained the same cloud data. So how do users get the most recent copy of the cloud. Do they need to delete their App and start over? Is there a .update command that can do this updating for me? Also, I pushed the App out of the background and restarted the App to obtain the updated cloud data.
So i created an App and for some time it was working fine. The app has features to show pdf to users without logging in. I needed to upload all data to cloudkit on public database.
I was not having knowledge that there are 2 mode being a noob in coding so after i saved all records in development mode in cloudkit when i published my app, i was not able to see them (Reason because live mode works in Production mode).
So i need help now to transfer data from development mode to production mode or any app or code that can help me upload all data in production mode.
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
CloudKit Dashboard
CloudKit Console
I'm trying to set up server-to-server authentication with CloudKit Web Services, but keep getting AUTHENTICATION_FAILED errors. I've tried multiple environment settings and debugging approaches without success.
What I've Tried
I created a Swift script to test the connection. Here's the key part that handles the authentication:
// Get current ISO 8601 date
let iso8601Formatter = ISO8601DateFormatter()
iso8601Formatter.formatOptions = [.withInternetDateTime]
let dateString = iso8601Formatter.string(from: Date())
// Create SHA-256 hash of request body
let bodyHash = SHA256.hash(data: bodyData).compactMap { String(format: "%02x", $0) }.joined()
// Get path from URL
let path = request.url?.path ?? "/"
// String to sign
let method = request.httpMethod ?? "POST"
let stringToSign = "\(method):\(path):\(dateString):\(bodyHash)"
// Sign the string with EC private key
let signature = try createSignature(stringToSign: stringToSign)
// Add headers
request.setValue(dateString, forHTTPHeaderField: "X-Apple-CloudKit-Request-ISO8601Date")
request.setValue(KEY_ID, forHTTPHeaderField: "X-Apple-CloudKit-Request-KeyID")
request.setValue(signature, forHTTPHeaderField: "X-Apple-CloudKit-Request-SignatureV1")
}
I've made a request to this endpoint:
What's Happening
I get a 401 status with this response:
"uuid" : "173179e2-c5a5-4393-ab4f-3cec194edd1c",
"serverErrorCode" : "AUTHENTICATION_FAILED",
"reason" : "Authentication failed"
}
What I've Verified
The key validates correctly and generates signatures
The date/time is synchronized with the server
The key ID matches what's in CloudKit Dashboard
I've tried all three environments: development, Development (capital D), and production
The container ID is formatted correctly
Debug Information
My debugging reveals:
The EC key is properly formatted (SEC1 format)
Signature generation works
No time synchronization issues between client and server
All environment tests return the same 401 error
Questions
Has anyone encountered similar issues with CloudKit server-to-server authentication?
Are there specific container permissions needed for server-to-server keys?
Could there be an issue with how the private key is formatted or processed?
Are there any known issues with the CloudKit Web Services API that might cause this?
Any help would be greatly appreciated!
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
Cloud and Local Storage
CloudKit JS
Hi Developer Community,
I'm experiencing a critical issue with CloudKit schema deployment that's blocking my app release. I've been trying to resolve this for several days and would appreciate any assistance from the community or Apple engineers.
Issue Description
I'm unable to deploy my CloudKit schema from development to production environment. When attempting to deploy through the CloudKit Dashboard, I either get an "Internal Error" message or the deployment button is disabled.
Environment Details
App: Reef Trak (Reef aquarium tracking app)
CloudKit Container: ************
Development Environment: Schema fully defined and working correctly
Production Environment: No schema deployed (confirmed in dashboard)
What I've Tried
Using the "Deploy Schema to Production" button in CloudKit Dashboard (results in "Internal Error")
Exporting schema from development and importing to production (fails)
Using CloudKit CLI tools with API token (results in "invalid-scope" errors)
Waiting 24-48 hours between attempts in case of propagation delays
Current Status
App works perfectly in development environment (when run from Xcode)
In TestFlight/sideloaded builds (production environment), the app attempts to fetch records but fails with "Did not find record type: Tank" errors
Log snippet showing the issue:
[2025-03-21] [CloudKit] Schema creation failed: Error saving record <CKRecordID: 0x******; recordName=SchemaSetup_Tank_-**---****, zoneID=_defaultZone:defaultOwner> to server: Cannot create new type Tank in production schema [2025-03-21] [CloudKit] Failed to create schema for Tank after 3 attempts [2025-03-21] [CloudKit] Error creating schema for Tank: Error saving record <CKRecordID: 0x****; recordName=SchemaSetup_Tank_---**-**********, zoneID=_defaultZone:defaultOwner> to server: Cannot create new type Tank in production schema
App Architecture & Critical Impact
My app "Reef Trak" is built around a core data model where the "Tank" entity serves as the foundational element of the entire application architecture. The Tank entity is not just another data type - it's the primary container that establishes the hierarchical relationship for all other entities:
All parameter measurements (pH, temperature, salinity, etc.) are associated with specific tanks
All maintenance tasks and schedules are tank-specific
All livestock (fish, corals, invertebrates) exist within the context of a tank
All user achievements and progress tracking depend on tank-related activities
Without the Tank schema being properly deployed to production, users experience what appears to be a completely empty application, despite successful authentication and CloudKit connection. The app shows "Successfully retrieved iCloud data" but displays no content because:
The Tank record type doesn't exist in production
Without Tanks, all child entities (even if their schemas existed) have no parent to associate with
This creates a cascading failure where no data can be displayed or saved
This issue effectively renders the entire application non-functional in production, despite working flawlessly in development. Users are left with an empty shell of an app that cannot fulfill its core purpose of reef tank management and monitoring.
The inability to deploy the Tank schema to production is therefore not just a minor inconvenience but a complete blocker for the app's release and functionality.
Questions
Is there an alternative method to deploy schema to production that I'm missing?
Could there be an issue with my account permissions or container configuration?
Are there known issues with the CloudKit Dashboard deployment functionality?
What's the recommended approach when the dashboard deployment fails?
I've also submitted a Technical Support Incident, but I'm hoping to get this resolved quickly as it's blocking my App Store release.
Thank you for any assistance!
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
CloudKit Dashboard
CloudKit Console
cktool
I've recently added iCloud backup on my chat app. Conversations are backing up fine but some users are losing their chats and when I see the telemetry it show "BAD_REQUEST" error. I couldn't find any details or solution for it.
Does anyone has any idea what it could be? My development scheme is already fully deployed to production.
Topic:
Developer Tools & Services
SubTopic:
Xcode Cloud
Tags:
CloudKit
iCloud Drive
CloudKit Console
I'm trying to find a way to create and use a test cloudkit container in my swiftdata-backed app.
I want to test pre-filling the model container with localized content at first run.
To do this I created a test cloudkit container, and assigned it to my debug build profile in settings and capabilities.
I then conditionally reference the test container in my apps cloudkit manager, i.e.:
private let db: CKDatabase
init() {
#if DEBUG
let container = CKContainer(identifier: "iCloud.com.team-name.myappname.testing-de") // Test CloudKit container
#else
let container = CKContainer(identifier: "iCloud.com.team-name.myappname") // Production CloudKit container
#endif
self.db = container.privateCloudDatabase
}
But when I run my app in debug, content is still created in the primary/production container.
Am I missing something? Or is there a better, or documented, way to test cloudkit more robustly?
Hey guys, I'm developing a Swift app, using iCloud to store some data in Containers, and the new Containers I created are iCloud.com.***.dev . Therefore, there is a storage called dev in Settings -> icloud -> Manage Account Storage. Currently, the app is still under development and has not been released to the Appstore.
My question: Settings -> icloud -> Manage Account Storage does not display my app name and icon, but only the suffix of the Containers id. Will this change after it is released to the Appstore? Are there any other control methods? Thank you
I implemented the cloudkit function, where users can connect with each other. The problem is, that if User A is doing a friend request and User B is accepting the request. The friend entry is correct visible for User B but not for User A. I can see in cloud kit that after the accepted request, the friend connection is set up correctly, also with the correct userID, but it not showing up for User A (the one that send the request)
It's in the public database. In this view you sign in using Apple Sign-In and create a specific user ID. Then you can access a global leaderboard to compare with all signed-in users. Additionaly, there’s a friend tab where you can search for and type in a specific user ID. The target user sees the friend request, can accept it, and then the accepted friend appears in their friend list. However, the original requester doesn’t see the connection after acceptance even though CloudKit shows the records Add comment. I've also tried to add a placeholder in for User A, that e.g he send the request and then has a placeholder where it says e.g pending request to User B. After User B accepted the request, the placeholder will go away and no friend connection is displayed, very strange.
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
CloudKit
Social
CloudKit Dashboard
CloudKit Console
It takes a few seconds, sometimes a few minutes for records to be downloaded back from CloudKit when the user reinstalls the app, which leads users to thinking their data was lost. I would like to know if there’s any way to provide a visual feedback about the current CloudKit sync status so I can let users know their data is being in fact downloaded back to their devices.
Hi everyone!
I have an app on the App Store that uses Core Data as its data store. (It's called Count on Me: Tally Counter. Feel free to check it out.) One of the app's core feature is an interactive widget with a simple button. When the button is tapped, it's supposed to update the entity in the store.
My requirement is that the changes are then reflected with minimal latency in the main app and – ideally – also on other devices of the same iCloud user. And vice-versa: When an entity is updated in the app (or on another device where the same iCloud user is logged in), the widget that shows this entity should also refresh to reflect the changes.
I have read multiple articles, downloaded sample projects, searched Stackoverflow and the Apple developer forums, and tried to squeeze a solution out of AI, but couldn't figure out how to make this work reliably.
So I tried to reduce the core problem to a minimal example project. It has two issues that I cannot resolve:
When I update an entity in the app, the widget is immediately updated as intended (due to a call to WidgetCenter's reloadAllTimelines method). However, when I update the same entity from the interactive widget using the same app intent, the changes are not reflected in the main app.
For the widget and the app to use the same local data store, I need to enable App Groups in both targets and set a custom location for the store within the shared app group. So I specify a custom URL for the NSPersistentStoreDescription when setting up the Core Data stack. The moment I do this, iCloud sync breaks.
Issue no. 1 is far more important to me as I haven't officially enabled iCloud sync yet in my real app that's already on the App Store. But it would be wonderful to resolve issue no. 2 as well. Surely, there must be a way to synchronize changes to the source of truth triggered by interactive widget with other devices of the same iCloud user. Otherwise, the feature to talk to the main app and the feature to synchronize with iCloud would be mutually exclusive.
Some other developers I talked to have suggested that the widget should only communicate proposed changes to the main app and once the main app is opened, it processes these changes and writes them to the NSPersistentCloudKitContainer which then synchronizes across devices. This is not an option for me as it would result in a stale state and potential data conflicts with different devices. For example, when a user has the same widget on their iPhone and their iPad, taps a button on the iPhone widget, that change would not be reflected on the iPad widget until the user decides to open the app on the iPhone. At the same time, the user could tap the button multiple times on their iPad widget, resulting in a conflicting state on both devices. Thus, this approach is not a viable solution.
An answer to this question will be greatly appreciated. The whole code including the setup of the Core Data stack is included in the repository reference above. Thank you!
I am working on a software where we want to add the feature to share the whole database with the other user. Database is iCloud combined with coredata. The other user(s) should be able to edit /delete and even create new objects in the share.
I did this with this code witch directly from sample code
let participants = try await ckConainer.fetchParticipants(matching: [lookupInfo], into: selectedStore)
for participant in participants {
participant.permission = .readWrite
participant.role = .privateUser
share.addParticipant(participant)
}
try await ckConainer.persistUpdatedShare(share, in: selectedStore)
the other user gets invited and I can see this in iCloud database that the other user is invited with status invited.
but the other user never gets a mail or something to accept and join the share. How does the other needs to accept the invitation ?
Hello !
I am using this iCloud key value pair mechanism to save small app configuration between iOS and tvOS.
I would say it is working. But when I go back and forth between debug and release (TestFlight) modes, it is like both apps are not connected anymore.
I spend a lot of time restarting all devices, rebuilding, activating / deactivating iCloud capabilities in the Xcode project.
It is like the app is mixing debug and release data.
Is there an easy way to check what is happening exactly ? I know there's nothing on CloudKit console, so ....
Thank you
Frederic
I am using cloudkit to save users high scores in a public database. The preference over using Game Center is because of simplicity and works really well for what I want to achieve. I simply want to let users know their global position. Because of data privacy laws the app asks the user for their permission to submit their score each time they get a new high score.
However, I have noticed that CKRecords under 'created' and 'modified' in addition to UTC time and date also contain creatorUserRecordID. Could this be a privacy issue? Can you extract any personal information from this? Can this be used to track back to the user? Is it linked to CKUserIdentity which I understand does contain personal information, although as I understand you need users consent to get this information. Under creatorUserRecordID it says... "Every user of the app has a unique user record that is empty by default. Apps can add data to the user record on behalf of the user, but don’t store sensitive data in it"
Currently I simply ask the user if they are happy to submit their score. But do I need to point out that it also stores a creatorUserRecordID? Obviously I don't want to do this if it is not needed as the user will 1) Probably not understand what a creatorUserRecordID is and 2) It makes the question complicated and will likely make most people refuse to submit their score.
If it is a privacy issue, is there anyway to stop a CKRecord creating this ID and simply save a score? All I need is a list of scores so the app can determine their current position.
If creatorUserRecordID does not contain any personal details and cannot be tracked back to the user please let me know, so I can be reassured that my current set up is fine and I am not causing any privacy issues!
This post did seem to indicate you may possibly be able to fetch personal details??
https://stackoverflow.com/questions/55782166/how-do-i-fetch-any-info-about-user-that-modified-ckrecord
I implemented the cloudkit function, where users can connect with each other. The problem is, that if User A is doing a friend request and User B is accepting the request. The friend entry is correct visible for User B but not for User A. I can see in cloud kit that after the accepted request, the friend connection is set up correctly, also with the correct userID, but it not showing up for User A (the one that send the request)
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
CloudKit
CloudKit Dashboard
CloudKit Console