2015-02-09 15 views
10

Ho attualmente ottenuto CloudKit istituito nella mia app in modo che io sono l'aggiunta di un nuovo record con l'aiuto del seguente codice sotto,CloudKit: recupera tutti i record con un determinato tipo di record?

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]; 

Tuttavia, ora mi piacerebbe essere in grado di recuperare tutti record che sono dello stesso tipo di record, "Stringhe" e restituiscono quelli compilati in un NSArray. Come potrei fare per farlo? Attualmente, tutto quello che ho capito è come recuperare ogni record individualmente, usando un recordID, che è una seccatura, ci deve essere un modo più semplice.

[_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

Secondo CKQuery API Reference: "predicati si basano su una stringa di formato. Non puoi utilizzare predicati basati su valori o blocchi. " Non penso che sia sempre stato così, ma attualmente nessuna delle due risposte sarebbe corretta perché usa 'NSPredicate (value:)' –

+0

@JamesLingo L'hai provato? è una supposizione? 'NSPredicate (value: true)' è completamente valido –

+0

L'ho usato in passato, ma chiunque lo facesse dovrebbe sapere che non è supportato per CloudKit, secondo la documentazione di Apple. Apple potrebbe benissimo fare cambiamenti che potrebbero infrangere quel codice, e può essere fatto senza l'uso di predicati basati su valori o blocchi. –

risposta

8

Aaaand, ho capito. Usando il codice qui sotto, sono stato in grado di creare una query da eseguire sul database, per poi restituire un NSArray nel blocco di completamento, che ho passato in loop, e ho restituito il valore per la chiave salvata in un 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

però non restituirà tutti i record, solo un sottoinsieme (di solito limitato a 100 per impostazione predefinita) –

+0

@MaxDesiatov cosa intendi con limitato? Come recuperare tutto? – Ryde

+0

Non importa, (100 limite) è la risposta qui: [collegamento] (http://stackoverflow.com/questions/29592964/ckquery-from-private-zone-returns-only-first-100-ckrecords-from-in -cloudkit) e [link] (http://stackoverflow.com/questions/27728115/limit-the-amount-of-results-returned-in-cloudkit) – Ryde

0

La funzione followig restituirà tutti i record per il tipo di record richiesto:

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

Ecco la risposta a 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

Soluzione Swift 4, mostra come recuperare tutti i record di tipo "YourTable", stampa anche System Field e 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 ?? "")") 
    }) 
}