2015-02-09 2 views
10

я в настоящее время получил CloudKit установить в моем приложении, так что я добавляю новую запись с помощью помощью следующего кода ниже,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]; 

Однако, сейчас я хотел бы быть в состоянии принести ВСЕ записи, имеющие один и тот же тип записи, «Строки» и возвращаемые скомпилированные в 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"]);    
    } 
}]; 
+0

Согласно CKQuery API Reference: «Предикаты основаны на строку формата. Вы не можете использовать предикаты, основанные на значении или на основе блоков. " Я не думаю, что это всегда было так, но в настоящее время ни один ответ не будет правильным, потому что они используют 'NSPredicate (value:)' –

+0

@JamesLingo Пробовали ли вы это? это предположение? 'NSPredicate (value: true)' полностью отлично –

+0

Я использовал его в прошлом, но каждый, кто это делает, должен знать, что он не поддерживается CloudKit, согласно собственной документации Apple. Apple может очень хорошо внести изменения, которые нарушили бы этот код, и это можно сделать w/out с использованием предикатов, основанных на значении или блоке. –

ответ

8

Aaaand, у меня оно есть. Используя приведенный ниже код, я смог создать запрос для запуска в базе данных, чтобы затем вернуть NSArray в блок завершения, через который я прошел цикл, и вернул значение для сохраненного ключа в NSLog.

NSPredicate *predicate = [NSPredicate predicateWithValue:YES]; 
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Strings" predicate:predicate]; 

[_privateDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) { 
    for (CKRecord *record in results) { 
     NSLog(@"Contents: %@", [record objectForKey:@"stringArray"]); 
    } 
}]; 
+1

это не вернет все записи, хотя, просто подмножество (обычно по умолчанию ограничено 100) –

+0

@MaxDesiatov, что вы имеете в виду с ограниченными? Как получить все? – Ryde

+0

Не обращайте на это внимание (100 лимит) здесь: [link] (http://stackoverflow.com/questions/29592964/ckquery-from-private-zone-returns-only-first-100-ckrecords-from-in -cloudkit) и [link] (http://stackoverflow.com/questions/27728115/limit-the-amount-of-results-returned-in-cloudkit) – Ryde

0

Функция followig возвращает все записи для запрошенного типа записи:

let database = CKContainer(identifier: "container_here").privateCloudDatabase 
typealias RecordsErrorHandler = ([CKRecord], Swift.Error?) -> Void 

func fetchRecords(forType type: String, completion: RecordsErrorHandler? = nil) { 

    var records = [CKRecord]() 

    let query = CKQuery(recordType: type, predicate: NSPredicate(value: true)) 
    let queryOperation = CKQueryOperation(query: query) 
    queryOperation.zoneID = CloudAssistant.shared.zone.zoneID 

    queryOperation.recordFetchedBlock = { record in 
     records.append(record) 
    } 

    queryOperation.queryCompletionBlock = { cursor, error in 

     self.fetchRecords(with: cursor, error: error, records: records) { records in 
      completion?(records, nil) 
     } 
    } 

    database.add(queryOperation) 
} 

private func fetchRecords(with cursor: CKQueryCursor?, error: Swift.Error?, records: [CKRecord], completion: RecordsHandler?) { 

    var currentRecords = records 

    if let cursor = cursor, error == nil { 

     let queryOperation = CKQueryOperation(cursor: cursor) 

     queryOperation.recordFetchedBlock = { record in 
      currentRecords.append(record) 
     } 

     queryOperation.queryCompletionBlock = { cursor, error in 
      self.fetchRecords(with: cursor, error: error, records: currentRecords, completion: completion) 
     } 

     database.add(queryOperation) 

    } else { 
     completion?(records) 
    } 
} 
2

Вот ответ на Swift 3.0.

func myQuery() { 
    let predicate = NSPredicate(value: true) 
    let query = CKQuery(recordType: "tableName", predicate: predicate) 

    publicDatabase.perform(query, inZoneWith: nil) { (record, error) in 

     for record: CKRecord in record! { 
      //... 

      // if you want to access a certain 'field'. 
      let name = record.value(forKeyPath: "Name") as! String     
     } 
    } 
} 
0

Раствор для Swift 4, показывает, как извлечь все записи типа "YourTable", также печатает System Field и Custom Field:

let query = CKQuery(recordType: "YourTable", predicate: NSPredicate(value: true)) 
CKContainer.default().publicCloudDatabase.perform(query, inZoneWith: nil) { (records, error) in 
    records?.forEach({ (record) in 

    // System Field from property 
    let recordName_fromProperty = record.recordID.recordName 
    print("System Field, recordName: \(recordName_fromProperty)") 

    // Custom Field from key path (eg: deeplink) 
    let deeplink = record.value(forKey: "deeplink") 
    print("Custom Field, deeplink: \(deeplink ?? "")") 
    }) 
} 
Смежные вопросы