2015-04-12 12 views
11

Cloudkit özel varsayılan bölgesi sorgusunun sonucuna herhangi bir sınır var mı?Özel bölgeden gelen CKQuery CloudKit'ten yalnızca ilk 100 CKRecords değerini döndürür

let p = NSPredicate(format: "(type == 'entered') AND (timestamp >= %@) AND (timestamp <= %@)", from, to) 
let q = CKQuery(recordType: self.beaconRecordType, predicate: p) 
q.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)] 
self.privateDatabase?.performQuery(q, inZoneWithID: nil, completionHandler: { results, error in 

    //count = 100 
    println(results.count) 

} 

Tamam: Ben yalnızca aşağıdaki sorgu ile ilk 100 kayıtları almak neden hiçbir ipucu var. Edwin cevabında bahsettiği gibi, çözüm, ilk veri bloğunu almak için CKQueryOperation'ı kullanmak ve daha sonra başka bir işlemi başlatmak için completeionBlock içindeki "imleci" kullanmaktır. Standart sorguları için varsayılan sınırı

GÜNCELLEME

func fetchBeacons(from:NSDate, to:NSDate) { 

    let p = NSPredicate(value: true) 
    let q = CKQuery(recordType: self.beaconRecordType, predicate: p) 

    let queryOperation = CKQueryOperation(query: q) 

    queryOperation.recordFetchedBlock = fetchedARecord 

    queryOperation.queryCompletionBlock = { [weak self] (cursor : CKQueryCursor!, error : NSError!) in 

     if cursor != nil { 
      println("there is more data to fetch") 
      let newOperation = CKQueryOperation(cursor: cursor) 
      newOperation.recordFetchedBlock = self!.fetchedARecord 
      newOperation.queryCompletionBlock = queryOperation.queryCompletionBlock 
      self!.privateDatabase?.addOperation(newOperation) 
     } 

    } 

    privateDatabase?.addOperation(queryOperation) 
} 

var i = 0 
func fetchedARecord (record: CKRecord!) { 
    println("\(NSDate().timeIntervalSinceReferenceDate*1000) \(++i)") 
} 
+0

ok. Bunu buldum. http://stackoverflow.com/a/27135836/893771. Bir parça kod olsa çok yardımcı olur. – CppChase

+0

[Bu yanıt] (http://stackoverflow.com/a/27728609/1966109) benzer bir soruya, tamamlanmamış durumdayken getirinizin sona ermesini önlemek için güçlü bir referansın 'queryOperation'da nasıl saklanacağını gösterir. –

+1

Bu çözüm işlemin sadece 3 kez çalışmasına neden olur !, bunun yerine şunu kullanın: http://stackoverflow.com/a/31664231/530884 – Shaybc

cevap

8

100 olduğu: İşte bir örnek. Bu miktar sabit değil. Toplam iCloud yüküne bağlı olarak değişebilir. Bu miktarı etkilemek istiyorsanız, o zaman CKQueryOperation'ı kullanmanız ve resultsLimit'i şu şekilde ayarlamanız gerekir: operation.resultsLimit = CKQueryOperationMaximumResults; Bu CKQueryOperationMaximumResults varsayılan ve 100 (çoğu zaman) ile sınırlandırır. Bu değeri çok yüksek ayarlamayın. Daha fazla kayıt istiyorsanız, daha fazla kayıt okumaya devam etmek için queryCompletionBlock imlecini kullanın.

+0

Büyük Edwin. Size daha önce cevap verdim :). Imlecin nasıl yapılacağını gösteren örnek kodunuz var mı? Bu benim için biraz zaman kazandı. – CppChase

+0

Üzgünüm, bunun için güzel bir örnek yok. Ama bu tehlikeli değil. Bunun gibi yeni bir sorguyu başlatabilirsiniz: var operation = CKQueryOperation (imleç: imleç) –

+2

Cevabınızı kabul ettim ve sorumu örnek kod ile güncelledim. Tnx dostum. – CppChase

1

Bu kodu, tüm kayıtların bir kayıt türünden alınabilmesi için projem için kullanıyorum, objektif c. İstenenKeys olarak "Giriş" kullanıyorum.

+ (void)fetchRecordsWithType:(NSString *)recordType 
      completionHandler:(void (^)(NSArray *records, NSError *error))completionHandler { 

    NSPredicate *truePredicate = [NSPredicate predicateWithValue:YES]; 

    CKQuery *query = [[CKQuery alloc] initWithRecordType:recordType 
               predicate:truePredicate]; 

    CKQueryOperation *queryOperation = [[CKQueryOperation alloc] initWithQuery:query]; 
    queryOperation.desiredKeys = @[@"Entry"]; 

    NSMutableArray *results = [NSMutableArray new]; 

    queryOperation.recordFetchedBlock = ^(CKRecord *record) { 

     [results addObject:record]; }; 

    queryOperation.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error) { 

     [self retrieveNextBatchOfQueryFromCursor:cursor 
             results:results 
              error:error 
           completionHandler:completionHandler]; }; 

    [[self CloudKitContainer].privateCloudDatabase addOperation:queryOperation]; } 


+ (void)retrieveNextBatchOfQueryFromCursor:(CKQueryCursor *)cursor 
            results:(NSMutableArray *)results 
            error:(NSError *)error 
         completionHandler:(void (^)(NSArray *records, NSError *error))completionHandler { 

    // CloudKit apparently has query limit 

    if (cursor != nil 
     && !error) { 

     CKQueryOperation *nextOperation = [[CKQueryOperation alloc] initWithCursor:cursor]; 

     nextOperation.recordFetchedBlock = ^(CKRecord *record) { 

      [results addObject:record]; }; 

     nextOperation.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error) { 

      [self retrieveNextBatchOfQueryFromCursor:cursor 
              results:results 
               error:error 
            completionHandler:completionHandler]; }; 

     [[self CloudKitContainer].privateCloudDatabase addOperation:nextOperation]; } 

    else { 

     dispatch_async(dispatch_get_main_queue(), ^(void){ 

      completionHandler(results, error); }); }} 
1

Tüm kayıtlar alınana kadar durmayacak bir tamamlama işleyici ile bir işlev içinde çalıştırmanın başka bir yolu. Bu, uygulama genelinde farklı farklı görünüm denetleyicileri tarafından yeniden kullanılabilir.

sorgu

func cloudKitLoadRecords(result: (objects: [CKRecord]?, error: NSError?) -> Void){ 

    // predicate 
    var predicate = NSPredicate(value: true) 

    // query 
    let cloudKitQuery = CKQuery(recordType: "ClassName", predicate: predicate) 

    // records to store 
    var records = [CKRecord]() 

    //operation basis 
    let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase 

    // recurrent operations function 
    var recurrentOperationsCounter = 101 
    func recurrentOperations(cursor: CKQueryCursor?){ 
     let recurrentOperation = CKQueryOperation(cursor: cursor!) 
     recurrentOperation.recordFetchedBlock = { (record:CKRecord!) -> Void in 
      print("-> cloudKitLoadRecords - recurrentOperations - fetch \(recurrentOperationsCounter++)") 
      records.append(record) 
     } 
     recurrentOperation.queryCompletionBlock = { (cursor:CKQueryCursor?, error:NSError?) -> Void in 
      if ((error) != nil) 
      { 
       print("-> cloudKitLoadRecords - recurrentOperations - error - \(error)") 
       result(objects: nil, error: error) 
      } 
      else 
      { 
       if cursor != nil 
       { 
        print("-> cloudKitLoadRecords - recurrentOperations - records \(records.count) - cursor \(cursor!.description)") 
        recurrentOperations(cursor!) 
       } 
       else 
       { 
        print("-> cloudKitLoadRecords - recurrentOperations - records \(records.count) - cursor nil - done") 
        result(objects: records, error: nil) 
       } 
      } 
     } 
     publicDatabase.addOperation(recurrentOperation) 
    } 

    // initial operation 
    var initialOperationCounter = 1 
    let initialOperation = CKQueryOperation(query: cloudKitQuery) 
    initialOperation.recordFetchedBlock = { (record:CKRecord!) -> Void in 
     print("-> cloudKitLoadRecords - initialOperation - fetch \(initialOperationCounter++)") 
     records.append(record) 
    } 
    initialOperation.queryCompletionBlock = { (cursor:CKQueryCursor?, error:NSError?) -> Void in 
     if ((error) != nil) 
     { 
      print("-> cloudKitLoadRecords - initialOperation - error - \(error)") 
      result(objects: nil, error: error) 
     } 
     else 
     { 
      if cursor != nil 
      { 
       print("-> cloudKitLoadRecords - initialOperation - records \(records.count) - cursor \(cursor!.description)") 
       recurrentOperations(cursor!) 
      } 
      else 
      { 
       print("-> cloudKitLoadRecords - initialOperation - records \(records.count) - cursor nil - done") 
       result(objects: records, error: nil) 
      } 
     } 
    } 
    publicDatabase.addOperation(initialOperation) 
} 

Kullanım Swift

cloudKitLoadRecords() { (queryObjects, error) -> Void in 
      dispatch_async(dispatch_get_main_queue()) { 
       if error != nil 
       { 
        // handle error 
       } 
       else 
       { 
        // clean objects array if you need to 
        self.objects.removeAll() 

        if queryObjects!.count == 0 
        { 
         // do nothing 
        } 
        else 
        { 
         // attach found objects to your object array 
         self.objects = queryObjects! 
        } 
       } 
      } 
     } 
+0

Mükemmel işlev, teşekkürler! –

0

basit örnek:

func fetchServices(completion: ErrorHandler? = nil) { 

    var records = [CKRecord]() 

    let query = CKQuery(recordType: "Service", predicate: NSPredicate(value: true)) 
    let queryOperation = CKQueryOperation(query: query) 

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

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

    database.add(queryOperation) 
} 

private func fetchServices(with cursor: CKQueryCursor?, error: Swift.Error?, records: [CKRecord], completion: ErrorHandler? = nil) { 

    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.fetchServices(with: cursor, error: error, records: currentRecords, completion: completion) 
     } 

     database.add(queryOperation) 

    } else { 
     parseAndSaveServices(with: records, completion: completion) 
    } 
} 
İlgili konular