2017-07-27 23 views
9

Chcę usunąć około 500 rekordów "odwiedzin" z publicznej bazy danych. CloudKit zapewnia tylko 100 rekordów na raz, więc wykorzystuję CKQueryCursor jak poniżej, aby uzyskać wszystkie potrzebne rekordy.CKError: Filtr kwerendy przekracza limit wartości: 250 dla kontenera

func fetchVisits(_ cursor: CKQueryCursor? = nil) { 
    print("fetchVisits \(cursor)") 
    var operation: CKQueryOperation! 
    if let cursor = cursor { 
     operation = CKQueryOperation(cursor: cursor) 
    } else { 
     let query = CKQuery(recordType: "Visit", predicate: NSPredicate(format: "Client IN %@ AND ANY Students IN %@", visitClients, visitStudents)) 
     operation = CKQueryOperation(query: query) 
    } 
    operation.recordFetchedBlock = { 
     (record) in 
     totalVisits.append(record) 
    } 
    operation.queryCompletionBlock = { 
     (cursor, error) in 
     if let error = error { 
      //handle error 
     } else if let cursor = cursor { 
      self.fetchVisits(cursor) 
     } else { 
      //all done! 
     } 
    } 
    CKContainer.default().publicCloudDatabase.add(operation) 
} 

nazywam funkcji jak:

fetchVisits() 

który działa dobrze, robi wszystkie razy, czego potrzebuję. Konsola Log

fetchVisits nil 
fetchVisits Optional(<CKQueryCursor: 0x174228140; id=4bb7887c326fc719, zone=(null)>) 
fetchVisits Optional(<CKQueryCursor: 0x17422a320; id=f67fb25669486da9, zone=(null)>) 
fetchVisits Optional(<CKQueryCursor: 0x174228380; id=7e87eb8b7cfe1a74, zone=(null)>) 
fetchVisits Optional(<CKQueryCursor: 0x17422cc80; id=e77e47ef2b29c8a4, zone=(null)>) 

Ale problem jest teraz chcę, aby odświeżyć kiedy wcisnąć przycisk i teraz daje mi ten błąd:

„Usługa niedostępna” (6/2022); "Żądanie nie powiodło się z kodem statusu HTTP 503"; Ponów próbę po 30.0 sekundach

Co jest dość oczywiste, myślę, że jestem przytłaczający serwer, żądając marnej 500 rekordów? Tak więc czekam 30 sekund i wywołuję funkcję ponownie i teraz dostaję ten błąd.

"Przekroczono limit" (27/2023); server message = "Filtr zapytań przekracza limit wartości: 250 dla kontenera

Z jakiegoś powodu nie mogę ponownie uruchomić tej funkcji.Jeśli ponownie uruchomię aplikację, działa poprawnie, ale tylko za pierwszym razem. specyficzne dla każdej tabeli, która zwraca CKQueryCursor. Mam inne tabele, które uderzam, które mają mniej niż 100 rekordów (więc kursor jest zerowy) i mogę je ciągnąć wiele razy bez żadnych problemów

Odpowiedz

4

OK, więc widziałem to wcześniej, a problem jest, jak sądzę, błędem na serwerach CloudKit. Z mojego doświadczenia wynika to ze złożonych zapytań.

Jeśli spróbować zmienić swoje orzeczenie do:

NSPredicate(value: true) 

lub nawet uproszczenie istniejącego poprzez usunięcie jakiejkolwiek części, które mogą być na tyle, aby go naprawić.

+1

Po prostu przetestowano to za pomocą tego predykatu: NSPredicate (format: "Client IN% @", visitClients), a teraz mogę wywołać pobieranie tyle razy, ile chcę, bez żadnych błędów serwera. Robię dodatkowy filtr predykatów na wynikach po ich pobraniu. Szkoda, ponieważ teraz uderzam w serwer i przynoszę WAY więcej rekordów niż potrzebuję bez żadnego powodu. –

1

Żądasz więcej CKRecords do iCloud przed zakończeniem operacji zapytania

... 
operation.queryCompletionBlock = { 
    (cursor, error) in 
    if let error = error { 
     //handle error 
    } else if let cursor = cursor { 
     self.fetchVisits(cursor) 
    } else { 
     //all done! 
    } 
} 
... 

Funkcja self.fetchVisits(cursor) wywołanie jest wykonywane wewnątrz bloku zakończenia, co oznacza, że ​​żądasz więcej rekordów, zanim zakończy się bieżąca operacja.

Możliwe rozwiązanie to użycie zamknięcia (completionHandler), w którym znajduje się CKQueryCursor, kiedy użytkownik potrzebuje więcej rekordów (przewiń tabelę lub coś w tym rodzaju), którą ponownie wywołujemy self.fetchVisits przekazując otrzymane cursos na twoje zamknięcie.

+0

Myślałem, że "queryCompletionBlock" było końcem operacji? Naprawię ten fragment, ale nie jestem pewien, czy to właśnie powoduje błąd. Widzę operację wykonaną 5 razy i pobierającą wszystkie potrzebne rekordy, ale kiedy później naciśniesz przycisk, aby ponownie wywołać funkcję, dostaję błędy serwera CloudKit. –

+0

Witam @WilliamT. Masz rację, queryCompletionBlock jest wykonywany tylko jeden raz. Jeśli mógłbyś napisać trochę więcej kodu, może mógłbym ci pomóc ... – Adolfo

+0

Dziękuję za pomoc, ale nie jestem pewien, o ile więcej kodu mogę opublikować.Powyższa funkcja działa doskonale, gdy uruchamiam ją po raz pierwszy, ale powoduje błędy serwera w kolejnych okresach, niewiele więcej kodu. –