标签: cloudkit

如何在CloudKit中使用资产?

我正在尝试将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 __)>具有需要加密但未在记录上找到保护数据的项目">

什么是"保护数据"?我应该在上传之前加密数据吗?

assets ios icloud cloudkit

8
推荐指数
1
解决办法
1126
查看次数

CloudKit CKModifyRecordsOperation给了我一个"保护数据不匹配"

我正在尝试使用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)

objective-c ios icloud cloudkit

8
推荐指数
2
解决办法
4112
查看次数

在CloudKit中获取CKReferences的最佳实践方法是什么?

在我的CloudKit设置中,我有一个Person记录类型,每个人都有一个Friend属于CKReference另一个Person对象的属性.

我拿了所有Person CKRecord的.我在桌子上列出这些人并将他们的朋友列在他们身上.目前我只是使用CKReference和单独获取每个朋友recordID.

这是我能看到的唯一方法,但最佳做法是什么?特别是因为我可能吸引了大量的朋友.单独获取所有这些对象似乎违反直觉.

我想知道是否有一个类似CoreData的方法,你可以选择在主要提取中获取相关对象?因此,例如,当我获取Person它时,它也会自动获取朋友.

objective-c ios cloudkit ckreference

8
推荐指数
1
解决办法
1130
查看次数

每天从特定记录类型中删除所有记录CloudKit

所以我想每天擦除特定记录类型的每条记录.所以基本上,我希望在凌晨12点擦除数据,以便第二天新鲜.我该怎么做呢?这是我可以在CloudKit仪表板中设置的,还是我必须以编程方式设置它?

ios swift cloudkit

8
推荐指数
3
解决办法
4080
查看次数

是否所有用户都使用相同的订阅接收公共数据库订阅通知?

我已经设置了CKSubscription*,以便我收到记录类型的更改.

我正在使用公共数据库.

当我使用相同的用户(相同的iCloud帐户)进行测试时,我会收到通知.

如果我使用其他用户(不同的iCloud帐户),我不会收到通知.

订阅是否仅适用于同一用户的设备之间?

以下是描述订阅的文档:

使用CKSubscription对象来跟踪服务器上发生的更改.订阅的作用类似于服务器上的持久查询,可以跟踪记录的创建,删除和修改.发生更改时,它们会触发推送通知的传递,以便您的应用可以正确响应.

https://developer.apple.com/library/ios/documentation/CloudKit/Reference/CKSubscription_class/index.html#//apple_ref/occ/cl/CKSubscription

无论哪个用户编辑记录,我都希望收到通知,并且订阅谓词仍应匹配.

UPDATE

*每个用户都有一个具有相同谓词的订阅,主要关注具有特定属性值的单个recordType.

此订阅的有效负载仅用于推送shouldSendContentAvailable = YES.

文件内容如下:

当此属性为YES时,服务器在推送通知的有效负载中包含content-available标志.该标志会导致系统唤醒或启动当前未运行的应用程序.然后,应用程序将获得后台执行时间,以下载与推送通知相关的任何数据,例如更改的记录集.如果应用程序已在前台运行,则包含此标志不会产生额外影响,并且通知将传递给应用程序代理以便照常处理.

recordType的安全权限是:

在此输入图像描述

进一步更新

检查设备未接收推送的日志,并且看到:

apsd[85]: Silent Push: Deny app not available
Run Code Online (Sandbox Code Playgroud)

重启设备,现在工作正常!

cloudkit

8
推荐指数
1
解决办法
2042
查看次数

CloudKit vs Parse

对于我即将推出的应用程序,我需要一个后端.所以对我来说最大的问题是:
Cloudkit还是Parse?现在两者都是跨平台("CloudKit JS"),这使问题变得更加困难.
你们有些人可以列出每个的优点/缺点吗?或者,如果您不知道两者,请就单一体验提出一些建议.

parse-platform mbaas cloudkit

8
推荐指数
2
解决办法
2218
查看次数

CKFetchRecordsOperation永远不会返回任何键

我的公共(开发)数据库中有一条记录,有几个填充字段.当我使用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字段的记录类型(参见上面的第一个更新),但它似乎没有改变任何东西.

swift cloudkit

8
推荐指数
1
解决办法
348
查看次数

CloudKit:基于CKQueryNotification删除本地对象

我正在构建一个严重依赖CloudKit进行数据同步的应用程序.每次应用程序启动时,它都会捕获使用a在服务器上进行的所有更改CKFetchNotificationChangesOperation.这会成功返回已创建和/或修改的所有对象,但我现在处于这个阶段,我还希望我的应用程序根据这些消息删除记录.

在我的应用程序中,我存储在CoreData中的每个对象也携带该对象的在线表示的recordID.这样我就可以轻松获取需要修改的对象.

删除对象时这似乎很难,因为CloudKit只返回这些对象的recordID,并且不提供我可以用来知道我在CoreData数据库中查找的对象的recordType.

在具有多种记录类型的情况下,如何正确处理CloudKit"已删除"通知?

core-data ios icloud swift cloudkit

8
推荐指数
1
解决办法
317
查看次数

CoreData+CloudKit | 开/关 iCloud 同步切换

我想让用户可以选择打开和关闭 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()会被调用。

任何帮助都会很棒,当然也欢迎其他方式!

谢谢。

core-data ios swift cloudkit

8
推荐指数
1
解决办法
2280
查看次数

在不影响CloudKit正确性的情况下执行持久历史记录清除的正确方法是什么?

目前,我们正在使用本地CoreData功能CloudKit,通过使用NSPersistentCloudKitContainer.

为什么我们启用持久历史跟踪功能?

由于/sf/answers/5078817971/中描述的问题,我们需要启用NSPersistentHistoryTrackingKey.


清除历史记录

基于https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes,我们应该手动执行持久历史记录清除。


但是,目前尚不完全清楚我们如何以安全的方式清除历史记录,而不影响 的正确性CloudKit。我们倾向于使用以下设置运行一些测试。

  1. 运行模拟器。我们将在模拟器中执行插入操作
  2. 运行真实设备。由于步骤 1,真实设备将收到静默推送通知。
  3. 模拟器和真实设备都运行相同的代码。
  4. 每当我们在模拟器中插入一个项目时,我们都会观察真实设备中发生的情况。

测试1:处理后立即清除所有历史数据

@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)

core-data ios swift cloudkit

8
推荐指数
1
解决办法
890
查看次数