我正在尝试将CloudKit与资产一起使用.
我创建的RecordType包含iCloud开发人员仪表板中的资产.
然后,我在公共数据库的默认区域中创建了一条记录,并将文件上传到记录的资产.
我写了这段代码来获取记录.
CKContainer *defaultContainer =[CKContainer defaultContainer];
CKDatabase *publicDatabase = [defaultContainer publicCloudDatabase];
CKRecordID *wellKnownID = [[CKRecordID alloc]
initWithRecordName:@"RECORDKEY"];
[publicDatabase fetchRecordWithID:wellKnownID
completionHandler:^(CKRecord *fetchedParty, NSError *error) {
NSLog(@"erorr : %@", error)
}];
Run Code Online (Sandbox Code Playgroud)
我收到此错误消息.
2014-06-28 21:42:50.148 AppName [10634:1068121] erorr:<CKError 0xc81b4a0:"内部错误"(1/5001); "记录<CKRecordID:0xc035b50; RECORDKEY:(_ defaultZone:__ defaultOwner __)>具有需要加密但未在记录上找到保护数据的项目">
什么是"保护数据"?我应该在上传之前加密数据吗?
我正在尝试使用CloudKit上传一些记录更改.我正在使用CKModifyRecordsOperation来批量上传设备上已更改的记录.记录都在自定义区域中
由于某种原因,操作不断回来,并告诉我""保护数据不匹配"
这是代码:
- (void)updloadLocalChangesWithCompletionBlock:(void (^)(NSError *error))completionBlock
{
// Initialize the data
NSArray *localChanges = self.localChanges;
NSArray *localDeletions = self.localDeletions;
// Initialize the database and modify records operation
CKDatabase *database = [CKContainer defaultContainer].privateCloudDatabase;
CKModifyRecordsOperation *modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:localChanges recordIDsToDelete:localDeletions];
modifyRecordsOperation.savePolicy = CKRecordSaveAllKeys;
NSLog(@"CLOUDKIT Changes Uploading: %d", localChanges.count);
// Add the completion block
modifyRecordsOperation.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) {
if (error) {
NSLog(@"[%@] Error pushing local data: %@", self.class, error);
}
[self.localChanges removeObjectsInArray:savedRecords];
[self.localDeletions removeObjectsInArray:deletedRecordIDs];
completionBlock(error);
}; …Run Code Online (Sandbox Code Playgroud) 在我的CloudKit设置中,我有一个Person记录类型,每个人都有一个Friend属于CKReference另一个Person对象的属性.
我拿了所有Person CKRecord的.我在桌子上列出这些人并将他们的朋友列在他们身上.目前我只是使用CKReference和单独获取每个朋友recordID.
这是我能看到的唯一方法,但最佳做法是什么?特别是因为我可能吸引了大量的朋友.单独获取所有这些对象似乎违反直觉.
我想知道是否有一个类似CoreData的方法,你可以选择在主要提取中获取相关对象?因此,例如,当我获取Person它时,它也会自动获取朋友.
所以我想每天擦除特定记录类型的每条记录.所以基本上,我希望在凌晨12点擦除数据,以便第二天新鲜.我该怎么做呢?这是我可以在CloudKit仪表板中设置的,还是我必须以编程方式设置它?
我已经设置了CKSubscription*,以便我收到记录类型的更改.
我正在使用公共数据库.
当我使用相同的用户(相同的iCloud帐户)进行测试时,我会收到通知.
如果我使用其他用户(不同的iCloud帐户),我不会收到通知.
订阅是否仅适用于同一用户的设备之间?
以下是描述订阅的文档:
使用CKSubscription对象来跟踪服务器上发生的更改.订阅的作用类似于服务器上的持久查询,可以跟踪记录的创建,删除和修改.发生更改时,它们会触发推送通知的传递,以便您的应用可以正确响应.
无论哪个用户编辑记录,我都希望收到通知,并且订阅谓词仍应匹配.
UPDATE
*每个用户都有一个具有相同谓词的订阅,主要关注具有特定属性值的单个recordType.
此订阅的有效负载仅用于推送shouldSendContentAvailable = YES.
文件内容如下:
当此属性为YES时,服务器在推送通知的有效负载中包含content-available标志.该标志会导致系统唤醒或启动当前未运行的应用程序.然后,应用程序将获得后台执行时间,以下载与推送通知相关的任何数据,例如更改的记录集.如果应用程序已在前台运行,则包含此标志不会产生额外影响,并且通知将传递给应用程序代理以便照常处理.
recordType的安全权限是:

进一步更新
检查设备未接收推送的日志,并且看到:
apsd[85]: Silent Push: Deny app not available
Run Code Online (Sandbox Code Playgroud)
重启设备,现在工作正常!
对于我即将推出的应用程序,我需要一个后端.所以对我来说最大的问题是:
Cloudkit还是Parse?现在两者都是跨平台("CloudKit JS"),这使问题变得更加困难.
你们有些人可以列出每个的优点/缺点吗?或者,如果您不知道两者,请就单一体验提出一些建议.
我的公共(开发)数据库中有一条记录,有几个填充字段.当我使用a CKFetchRecordsOperation来获取该记录时,获取成功,但结果CKRecord始终不包含任何键.无论我是明确设置desiredKeys我的提取操作还是将其保留为nil,都会发生这种情况.记录及其密钥长期保持不变,因此不是传播延迟.
公共数据库中只有一条记录,其ID与我得到的记录相符,所以我确信正在记录正确的记录; 它从来没有任何钥匙.例如,以下代码始终打印keys: [].
let op = CKFetchRecordsOperation(recordIDs:[...])
op.desiredKeys = [...] // commenting this has no effect
op.fetchRecordsCompletionBlock = {records, error in
if let e = error {
print("error:", e)}
for (id, r) in records ?? [:] {
print("keys:", r.allKeys())}}
db.addOperation(op)
Run Code Online (Sandbox Code Playgroud)
我也试过通过下标符号访问各个键,但它们总是如此nil.我现在处于亏损状态.没有错误,我想要的记录被发现,为什么没有任何密钥?
更新:我注意到CloudKit仪表板总是在左下角显示"重新编制索引",即使在我上次更改后的几天内也是如此.此外,我尝试创建第二条记录(通过仪表板),在留下足够的时间进行传播后,我的提取甚至无法找到它.
在从这个SO问题链接到Apple开发者论坛帖子关于这个问题之后,我发现一个帖子表明它只发生在包含Asset字段的记录中.我会在有空的时候尝试尝试,虽然在这种情况下我无法避免使用资产,所以它可能没什么帮助.
更新2:我尝试重置我的开发环境,然后重新创建与以前相同的记录.从好的方面来说,CloudKit仪表板中的"重新索引"消息终于消失了.不幸的是,我的代码现在无法找到我的任何记录,即使代码保持不变并且我已经对所有内容进行了三重检查.
我也尝试创建一个没有Asset字段的记录类型(参见上面的第一个更新),但它似乎没有改变任何东西.
我正在构建一个严重依赖CloudKit进行数据同步的应用程序.每次应用程序启动时,它都会捕获使用a在服务器上进行的所有更改CKFetchNotificationChangesOperation.这会成功返回已创建和/或修改的所有对象,但我现在处于这个阶段,我还希望我的应用程序根据这些消息删除记录.
在我的应用程序中,我存储在CoreData中的每个对象也携带该对象的在线表示的recordID.这样我就可以轻松获取需要修改的对象.
删除对象时这似乎很难,因为CloudKit只返回这些对象的recordID,并且不提供我可以用来知道我在CoreData数据库中查找的对象的recordType.
题
在具有多种记录类型的情况下,如何正确处理CloudKit"已删除"通知?
我想让用户可以选择打开和关闭 iCloud 同步。
经过一段时间的研究,我发现实现这一目标的一种方法是将cloudKitContainerOptions.
nil因此,如果我不想同步数据库,我会将其设置为。
if(!UserDefaultsManager.shared.iCloudSyncOn) {
description.cloudKitContainerOptions = nil
}
Run Code Online (Sandbox Code Playgroud)
这一切都工作正常,但我还没有找到在运行时执行此操作的方法。
我尝试在用户切换时重新初始化我的容器,以便我的容器cloudKitContainerOptions根据选择而有所不同。
但这只会在保存上下文时返回一个错误,说:Thread 1: "Illegal attempt to establish a relationship 'addEntries' between objects in different contexts ...,我认为这是由于重新初始化造成的。
我想我必须将新创建的上下文传递到我的整个视图层次结构,任何缓存 moc 的东西?
这是我的 CoreDataStack 的简化片段:
func setupContainer() -> NSPersistentContainer {
let container = NSPersistentCloudKitContainer(name: "...")
guard let description = container.persistentStoreDescriptions.first else { ... }
...
if(!UserDefaultsManager.shared.iCloudSyncOn) {
description.cloudKitContainerOptions = nil
}
container.loadPersistentStores(completionHandler: { ... })
...
return container
}
Run Code Online (Sandbox Code Playgroud)
当用户切换时,setupContainer()会被调用。
任何帮助都会很棒,当然也欢迎其他方式!
谢谢。
目前,我们正在使用本地CoreData功能CloudKit,通过使用NSPersistentCloudKitContainer.
由于/sf/answers/5078817971/中描述的问题,我们需要启用NSPersistentHistoryTrackingKey.
基于https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes,我们应该手动执行持久历史记录清除。
但是,目前尚不完全清楚我们如何以安全的方式清除历史记录,而不影响 的正确性CloudKit。我们倾向于使用以下设置运行一些测试。
@objc func storeRemoteChange(_ notification: Notification) {
// Process persistent history to merge changes from other coordinators.
historyQueue.addOperation {
self.processPersistentHistory()
}
}
/**
Process persistent history, posting any relevant transactions to the current view.
*/
private func processPersistentHistory() {
backgroundContext.performAndWait {
// Fetch history received from outside the app since the last token
let …Run Code Online (Sandbox Code Playgroud) cloudkit ×10
ios ×7
swift ×5
core-data ×3
icloud ×3
objective-c ×2
assets ×1
ckreference ×1
mbaas ×1