11

公開データベースから約 500 件の「訪問」レコードを取得したいと考えています。CloudKit は一度に 100 レコードしか提供しないため、以下のように CKQueryCursor を使用して、必要なすべてのレコードを取得します。

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)
}

私は次のように関数を呼び出します:

fetchVisits()

それはうまくいきます、それは私が必要とするすべての訪問を取得します。コンソール ログ

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)>)

しかし、問題は、ボタンを押したときに更新したいのですが、次のエラーが表示されることです。

「サービス利用不可」(2022 年 6 月); "リクエストは http ステータス コード 503 で失敗しました"; 30.0 秒後に再試行

これはかなり自明ですが、わずか500件のレコードをリクエストすることでサーバーを圧倒していると思いますか? したがって、30 秒待って関数を再度呼び出すと、このエラーが発生します。

「制限を超えました」(2023年27月); サーバー メッセージ = "クエリ フィルターが値の制限を超えています: コンテナーの 250

何らかの理由で、その機能を再度実行できません。アプリを再起動すると、再び正常に動作しますが、初回のみです。この問題は、CKQueryCursor を返すすべてのテーブルに固有のようです。私がヒットしている他のテーブルには、100 未満のレコードがあり (したがって、カーソルは nil です)、問題なくそれらを複数回プルできます。

4

3 に答える 3

1

クエリ操作が完了する前に、iCloud にさらに CKRecords を要求しています。

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

関数self.fetchVisits(cursor)呼び出しは完了ブロック内で行われます。これは、現在の操作が完了する前に、より多くのレコードを要求していることを意味します。

考えられる解決策は、CKQueryCursor を含むクロージャー (completionHandler) を使用することです。ユーザーがさらにレコードを必要とする (テーブルをスクロールするなど) 場合は、クロージャーで受け取ったカーソルをself.fetchVisits渡してもう一度呼び出します。

于 2017-07-27T10:34:16.950 に答える