【发布时间】:2018-08-26 20:15:29
【问题描述】:
我用于使用 CloudKit 为我的应用获取记录的 api 不再正常工作。它只是在一两个星期前才开始这样做。它从公共数据库中获取很好,而不是从私有数据库中获取。
例如,我有一个名为“Part”的记录类型,其中包含一些值,包括“dateamp”字段。第一次启动应用程序时,它应该使用 CKQueryOperation 在私有数据库中获取 Part(和其他)的所有记录,然后在后续启动时,它使用 CKFetchRecordZoneChangesOperation 获取任何新记录。在我的个人 iCloud 帐户中,我有超过 1,000 条这样的记录。但是查询操作和获取更改操作只能获取完全相同的 107 条记录,不能再获取更多。这不是 resultLimits 的问题,我已经实现了对 CKQueryCursor 的检查。作为一个实验,我给它一个谓词,只获取时间戳为 2018 年 1 月或更晚的记录——它返回 0 记录。还有另一种记录类型,在我的数据库中有 12 条记录,但只有 1 正在同步。
我将同步类设计为跨平台 API。它适用于我的 iOS、macOS 和 tvOS 目标。 macOS 目标同步良好,即使它使用完全相同的代码行。 iOS 和 tvOS 已经运行了将近 2 年。除了现在在 NSOperation 子类中使用该类之外,几乎没有任何改变。我在多个 iPhone、iPad、iOS 模拟器实例、iOS 版本、Xcode 版本上进行了尝试。我尝试了不同的 iCloud 帐户。我不知道问题是什么。但是这个错误使我无法发布急需的更新。我想这可能只是 Apple 在开发环境中的一个错误,并且在公开发布时可以正常工作,但我害怕禁用我的所有用户。
protocol CloudData {
var privateDatabase : CKDatabase { get }
}
extension CloudData {
var privateDatabase : CKDatabase {
return CKContainer (identifier: "iCloud...").privateDatabase
}
}
final class CloudSync : CloudData {
func initialSync {
...
// Create an operation to fetch all PARTS
let partQuery = CKQuery (recordType: "Part", predicate: NSPredicate(value: true))
let partOperation = CKQueryOperation (query: partQuery)
partOperation.recordFetchedBlock = { partRecords += [$0] }
partOperation.zoneID = zoneID
partOperation.queryCompletionBlock = { cursor, error in
if let cursorObj = cursor {
print("Initial Sync - Cursor Found Parts")
let newOp = CKQueryOperation (cursor: cursorObj)
newOp.recordFetchedBlock = partOperation.recordFetchedBlock
newOp.queryCompletionBlock = partOperation.queryCompletionBlock
self.privateDatabase.add(newOp)
return
}
self.progress.completedUnitCount += 1
print ("Initial Sync - Part Objects Fetched")
}
partOperation.database = privateDatabase
...
}
}
【问题讨论】:
-
(1) 显示定义 privateDatabase 的行。 (2) 以下是什么意思? “例如,我有一条名为“Part”的记录,其中包含一些值,包括“dateamp”字段。第一次启动应用程序时,它应该在私有数据库中获取 Part(和其他)的所有记录使用 CKQueryOperation,然后在后续启动时,它会使用 CKFetchRecordZoneChangesOperation 获取任何新的。”部分是记录?并试图获取 Part(记录)的所有记录?这没有意义。
-
我对 2 号表示歉意。我错过了输入我的描述。 “部分”是一个记录类型。在 Core Data 术语中,它将是一个“实体”。因此,例如,用户将使用 { datestamp = Mar 2018, name = Dan's Part, description = part for Dan} 之类的数据创建一个“Part”CKRecord。所以应用程序第一次启动时,它会获取该类型的所有记录。然后,它只获取添加的新记录 - 就像他们有第二个添加记录的设备一样,那么第一个设备将使用 CKFetchRecordZoneChanges 获取第二个设备创建的新记录。
-
“privateDatabase”只是一个在协议中定义并在协议扩展中实现的属性。像这样 - var privateDatabase : CKDatabase { return CKContainer (identifier: "iCloud....").privateDatabase } 。 CloudSync 类符合协议。为简洁起见,我只是省略了上面示例中类定义中的所有协议一致性。
-
如果您建议不能仅为私有数据库获取数据,那么您可能需要处理安全角色。
-
我想过。我将对此进行更多研究。但事实是我可以从私有数据库中获取,只是它只能获取有限数量的我的记录。它从不出错,只返回我正在查询的记录的一小部分——我知道这些记录在那里。每一条记录都是我创造的。除此之外,相同的数据库,使用相同的 API,查询相同的记录,使用相同的 iCloud 帐户,每次都适用于我的应用程序的 macOS 版本。如果获取所有 1,200 条记录。我可能不得不将我的一个 TSI 用于 Apple。