我目前在我的应用程序中设置了CloudKit,以便我使用以下代码的帮助添加新记录,
CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:@"stringArray"];
CKRecord *record = [[CKRecord alloc] initWithRecordType:@"Strings" recordID:recordID];
[record setObject:[NSArray arrayWithObjects:@"one", @"two", @"three", @"four", nil] forKey:@"stringArray"];
[_privateDatabase saveRecord:record completionHandler:nil];
Run Code Online (Sandbox Code Playgroud)
但是,现在我希望能够获取具有相同记录类型的所有记录"Strings",并将这些记录返回到NSArray中.我该怎么做呢?目前,我所知道的是如何使用recordID单独获取每条记录,这是一个麻烦,必须有一个更简单的方法.
[_privateDatabase fetchRecordWithID:recordID completionHandler:^(CKRecord *record, NSError *error) {
if (error) {
// Error handling for failed fetch from private database
}
else {
NSLog(@"ICLOUD TEST: %@", [record objectForKey:@"stringArray"]);
}
}];
Run Code Online (Sandbox Code Playgroud) 我正在尝试保存记录CloudKit但是我从cloudkit中收到以下错误:
error saving record este es error: Error saving record <CKRecordID: 0x7fef15b5d2a0; 2:(_defaultZone:__defaultOwner__)> to server: WRITE operation not permitted
Run Code Online (Sandbox Code Playgroud)
以下是我试图保存记录的方法:
[publicDatabase saveRecord:recordContent completionHandler:^(CKRecord *record, NSError *error){
if (!error)
{
NSLog(@"saved!!!");
}
else
{
if ([[error.userInfo valueForKey:@"ErrorDescription"] isEqualToString:@"record to insert already exists"])
{
NSLog(@"record already exist %@",[error.userInfo valueForKey:@"ErrorDescription"]);
}
NSLog(@"error saving record : %@",error.localizedDescription);
}
}];
Run Code Online (Sandbox Code Playgroud)
但之前我检查过cloudkit是否可用:
[myContainer accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError *error)
{
NSLog(@" no error but status %ld",accountStatus);
if (((accountStatus == 3) || (accountStatus == 2)) && (!error))
{
NSLog(@" …
Run Code Online (Sandbox Code Playgroud) 我的谓词想要排除已经下载并在[CKRecordID]中可用的一些记录.现在我可以查询1个CKRecordID [0],但不能查询[CKRecordID]数组.我该如何查询数组?
let excludeIDs: [CKRecordID]
Run Code Online (Sandbox Code Playgroud)
这有效:
let pred1 = NSPredicate(format: "NOT(recordID = %@)", excludeIDs[0])
Run Code Online (Sandbox Code Playgroud)
但这不是:
let pred1 = NSPredicate(format: "NOT(recordID IN %@)", excludeIDs)
Run Code Online (Sandbox Code Playgroud)
错误:loadImageCompareRecordIDsAndEndDateThatHaveNotEnded错误:无效谓词:无效谓词:数组成员必须符合CKRecordValue :("","","","","")(CKRecordID)
代码的其他一般部分:
let sort = NSSortDescriptor(key: "creationDate", ascending: false)
let query = CKQuery(recordType: MyRecordTypes.ImageCompare, predicate: pred1)
query.sortDescriptors = [sort]
let operation = CKQueryOperation(query: query)
operation.desiredKeys = ["endDate"]
operation.resultsLimit = 50
Run Code Online (Sandbox Code Playgroud) CKQuery
doc说:谓词中使用的键名对应于当前评估记录中的字段.键名可以包括记录的元数据属性的名称,例如"creationDate"或您添加到记录中的任何数据字段.
我可以在其中使用哪些元数据CKQuery
?我能用record.recordID.recordName
,如果有key
,它的用途是什么?
假设我有一个'物种'记录类型,其中包含由许多用户创建的公共记录.目前,我的查询检索"物种"的所有记录:
private func fetchSpecies() {
// Fetch Public Database
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
// Initialize Query
let query = CKQuery(recordType: "Species", predicate: NSPredicate(format: "TRUEPREDICATE"))
// Configure Query
query.sortDescriptors = [NSSortDescriptor(key: "latinName", ascending: true)]
// Perform Query
publicDatabase.performQuery(query, inZoneWithID: nil) { (records, error) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// Process Response on Main Thread
self.processResponseForQuery(records, error: error)
})
}
}
Run Code Online (Sandbox Code Playgroud)
如何只获取当前用户创建的记录(如设备所有者)?
谢谢!
这个问题询问是否可以CKRecord
在Swift中使用下标.虽然我已经知道如何做提问者想要的东西,但是它的每个排列都会给我一个堆栈溢出:
subscript(key: String) -> CKRecordValue? {
get {
return objectForKey(key) as CKRecordValue?
}
set {
setObject(newValue, forKey: key)
}
}
Run Code Online (Sandbox Code Playgroud)
堆栈溢出发生在getter中.(我从来没有尝试过的制定者,所以它可能有发生了.)我已经试过与实施objectForKey:
,objectForKeyedSubscript:
以及valueForKey:
.所有都产生相同的结果:堆栈溢出.
这很奇怪,因为CKRecord
肯定是用Objective-C编写的.为什么它会以递归方式调用Swift的subscript
方法?这没有道理.Nate Cook在对提问者的回答中,想知道为什么Swift不会objectForKeyedSubscript:
自动桥接.好吧,也许这样做的代码没有完全烘焙,但是导致了这个问题.我将不得不尝试与另一个类objectForKeyedSubscript:
.
它似乎objectForKeyedSubscript:
通常是桥接的.我使用适当的方法在Objective-C中创建了一个类,将其添加到桥接头,并且索引器在那里编译而没有问题.更好的是,它没有堆栈溢出.
这意味着正在发生一些非常不寻常的事情CKRecord
.
如果你在Swift中创建一个类,NSObject
并subscript
使用a String
作为键来实现它的方法,那就变成了objectForKeyedSubscript:
.(对于"纯Swift"类,我怀疑情况并非如此.)您可以通过将Swift类导入Objective-C并验证objectForKeyedSubscript:
是否存在来验证这一点.
从CKRecord
下降开始NSObject
,实现subscript
覆盖默认实现.此外,它似乎objectForKey:
和valueForKey:
所有最终叫objectForKeyedSubscript:
,这会导致(读:"是一样的")的调用subscript
,这会导致堆栈溢出.
这可以解释为什么发生堆栈溢出.它仍然没有解释为什么objectForKeyedSubscript:
没有自动桥接,但也许是因为定义setObject:forKeyedSubscript:
与规范的类型签名略有不同:- …
如果recordName
在客户端生成,它可以提供更流畅的用户体验.
var uuid = NSUUID().UUIDString
Run Code Online (Sandbox Code Playgroud)
你知道这样做有什么不利吗?
是否可以使用Swift CKRecord
在一个CloudKit
操作中保存多个对象?我知道如何一次检索多个记录,使用类似CKFetchRecordsOperation
甚至只是常规的东西performQuery
.我刚刚意识到我不确定在一次操作中保存多个新记录的方法.到目前为止,我一直这样做的方式对我来说似乎效率低下.例如:
let recordsToSave:[CKRecord]!
for newRecord in recordsToSave {
if let database = self.publicDatabase {
database.saveRecord(newRecord, completionHandler: { (record:CKRecord?, error:NSError?) in
// Check if there was an error
if error != nil {
// There was an error, handle it properly.
}
else {
// There wasn't an error
if let savedRecord = record {
// Handle saved record accordingly.
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
虽然这确实很好用,但在我看来它似乎效率极低.我认为让一个特定的函数调用来保存整个数组会更有意义CKRecords
,而不是每次都要通过循环调用数据库.基本上这就是我希望我能做到的:
let recordsToSave:[CKRecord]!
if let …
Run Code Online (Sandbox Code Playgroud) 我的应用程序中有2个视图控制器.
第一个"MainViewController"显示一个tableView,其中包含从私有CloudKit数据库获取的CKRecords字段.在此VC的viewWillAppear方法中,我从CloudKit获取记录并重新加载tableview的数据,以显示先前由用户保存在CloudKit中的最新获取结果.
第二个视图控制器"CreateRecordViewController"用于创建CKRecords并将它们保存到CloudKit的私有数据库.
所以我在CreateRecordViewController中创建记录并在MainViewController中显示它们.
问题如下:当我在CreateRecordViewController创建记录时,它在CloudKit服务器上保存,但在关闭此CreateRecordViewController并转到MainViewController之后,tableview并不总是及时更新.
这是我的CreateRecordViewController中保存记录的代码:
CloudKitManager.sharedInstance.privateDatabase.save(myRecord) { (savedRecord, error) -> Void in
if error == nil {
print("successfully saved record code: \(savedRecord)")
}
else {
// Insert error handling
print("error Saving Data to iCloud: \(error.debugDescription)")
}
}
Run Code Online (Sandbox Code Playgroud)
记录保存后,关闭CreateRecordViewController并查看MainViewController.
正如我之前在MainViewController的viewWillAppear中所述,我检查iCloud是否可用,如果它可用,我从CloudKit获取所有记录并在tableView中显示它们.
override func viewWillAppear(_ animated: Bool) {
CKContainer.default().accountStatus { (accountStatus, error) in
switch accountStatus {
case .noAccount: print("CloudKitManager: no iCloud Alert")
case .available:
print("CloudKitManager: checkAccountStatus : iCloud Available")
self.loadRecordsFromiCloud()
case .restricted:
print("CloudKitManager: checkAccountStatus : iCloud restricted")
case .couldNotDetermine:
print("CloudKitManager: checkAccountStatus : …
Run Code Online (Sandbox Code Playgroud)