CloudKit:防止重复logging

我正在通过一个应用程序将数据从外部Web服务转移到私有CloudKit数据库。 该应用程序是一个单用户应用程序,但是我遇到了一个竞争条件,我不知道如何避免。

我的外部数据中的每条logging都有一个唯一的标识符映射到我的CKRecord实例。 一般的应用程序启动stream程是:

  1. 获取相关loggingtypes的当前CKRecords。
  2. 获取外部logging。
  3. 对于每个外部logging,如果在CloudKit中不存在,则通过批量创build(修改操作)创build它。

现在的问题是,如果同时在用户的两台设备上启动这个进程,由于CK和外部提取都是asynchronous的,所以很有可能会得到重复的logging。

我知道我可以使用区域自动提交所有的CKRecord实例,但我不认为这解决了我的问题,因为如果所有这些提取都发生在同一时间,保存并不是真正的问题。

我的问题是:

  1. 有没有人知道一种方法来“locking”私人数据库的所有用户的设备写入?
  2. 另外,有没有办法强制在任何CKRecord字段唯一性?
  3. 或者,有没有办法使用自定义值作为主键,在这种情况下,我可以使用我的外部ID作为CK ID,并允许系统本身防止重复。

我在这里先向您的帮助表示感谢!

回答:

  1. 不,你不能locking私人数据库
  2. Cloudkit已经实施并假定您的loggingID是唯一的
  3. 你可以使任何你喜欢的loggingID(在非区域部分)。

说明:

关于你的重复问题。 如果你是创buildloggingID的人(例如你提到的外部logging),那么最糟糕的情况是,如果你有一个竞争条件,你应该有一个logging,用另一个logging写相同的数据。 我不认为这是一个极端的情况下两个设备在同一时间启动这个过程的问题。 基本上你首先获取现有logging然后修改它们的逻辑似乎听起来对我来说。

码:

//employeeID is a unique ID to identify an employee let employeeID = "001" //Remember the recordID needs to be unique within the same database. //Assuming you have different record types, it is better to prefix the record name with the record type so that it is unique let recordName = "Employee-\(employeeID)" //If you are using a custom zone let customZoneID = CKRecordZoneID(zoneName: "SomeCustomZone", ownerName: CKCurrentUserDefaultName) let recordIDInCustomZone = CKRecordID(recordName: recordName, zoneID: customZoneID) //If you are using the default zone let recordIDInDefaultZone = CKRecordID(recordName: recordName) 

当我试图读取超过100条logging的数据库时,我有类似的重复下载问题; 该解决scheme可以在Apple的Atlas示例中find,该示例使用布尔值来检查最后一个进程在启动下一个进程之前是否完成。 你find一个这样的块

 @synchronized (self) { // Quickly returns if another loadNextBatch is running or we have the oldest post if(self.isLoadingBatch || self.haveOldestPost) return; else self.isLoadingBatch = YES; } 

顺便说一句,这里的代码来创build您自己的logging密钥。

 CKRecordID *customID = [[CKRecordID alloc] initWithRecordName: [globalEOConfirmed returnEOKey:i]]; newrecord = [[CKRecord alloc] initWithRecordType:@"Blah" recordID:customID];