Обработка ошибок Cloudkit не вызывается, если qualityOFService отсутствует - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь обработать ошибки Cloudkit.Я прочитал этот пост: CloudKit - полный и полный пример обработки ошибок , но у меня есть несколько вопросов:

1. Почему обработка ошибок не работает, если я не установил .qualityOFService.userInitiated правильно, так как в упомянутом сообщении установлено .background ?.Кроме того, мне нужно установить его для loadDataAgain()?

2.Как я могу сделать обработку ошибок многоразовой, которая будет принимать ошибку и другой параметр (в соответствии с viewcontroller, который вызывается из)?

 @objc func loadData() {
    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: myRecordType.type, predicate: predicate)
    query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.resultsLimit = 5
   //if the below line is missing errors will not be handled
    queryOperation.qualityOfService = .userInitiated
    queryOperation.recordFetchedBlock = { item in
        self.array.append(item)
    }
    queryOperation.queryCompletionBlock = { cursor, error in
        if error != nil{
          if let ckerror = error as? CKError {
            if ckerror.code == CKError.requestRateLimited {
                let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                DispatchQueue.main.async {
                    Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.loadData), userInfo: nil, repeats: false)
                }
            } else if ckerror.code == CKError.zoneBusy {
                let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                DispatchQueue.main.async {
                    Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.loadData), userInfo: nil, repeats: false)
                }
            } else if ckerror.code == CKError.limitExceeded {
                let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                DispatchQueue.main.async {
                    Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.loadData), userInfo: nil, repeats: false)
                }
            } else if ckerror.code == CKError.notAuthenticated {
                //present relevant alert with action to reload ViewController
            } else if ckerror.code == CKError.networkFailure {
                //present relevant alert with action to reload ViewController
            } else if ckerror.code == CKError.networkUnavailable {
                //present relevant alert with action to reload ViewController
            } else if ckerror.code == CKError.quotaExceeded {
                //present relevant alert with action to reload ViewController
            } else if ckerror.code == CKError.partialFailure {
                //present relevant alert with action to reload ViewController
            } else if (ckerror.code == CKError.internalError || ckerror.code == CKError.serviceUnavailable) {
                //present relevant alert with action to reload ViewController
            }
        }
        }
        else{
            if cursor != nil {
                self.loadDataAgain(cursor!)
            }
        }
        OperationQueue.main.addOperation {
            self.tableView.reloadData()
        }
}

func loadDataAgain(_ cursor: CKQueryOperation.Cursor) {
    let queryOperation = CKQueryOperation(cursor: cursor)
    queryOperation.resultsLimit = 5

    queryOperation.recordFetchedBlock = { item in
        self.array.append(item)
    }
    queryOperation.queryCompletionBlock = { cursor, error in
        if error != nil{
            //have the same error handling as above
        }
        else{
            if cursor != nil {
                self.loadDataAgain(cursor!)
            }
        }
        OperationQueue.main.addOperation {
            self.tableView.reloadData()
        }
    }
    Database.share.publicDB.add(queryOperation)
}

1 Ответ

0 голосов
/ 12 октября 2018

Относительно вашего первого вопроса , см. этот ответ , который предполагает, что ошибки не сообщаются при более низких настройках качества обслуживания:

это потому, что[] система ожидает улучшения состояния сети, в то время как [если] вы устанавливаете .default или .userInitiated, система ожидает ответа «в реальном времени»

Если вы посмотрите на Документы об энергоэффективности, Apple, кажется, подтверждает этот подход, говоря, что

CKOperation является подклассом класса NSOperation.Хотя класс NSOperation имеет уровень QoS по умолчанию NSQualityOfServiceBackground, объекты CKOperation имеют уровень QoS по умолчанию NSQualityOfServiceUtility.На этом уровне сетевые запросы рассматриваются как дискреционные, когда ваше приложение не используется.На айфонах дискреционные операции приостанавливаются, когда включен режим низкого энергопотребления.

Вам нужно будет явно установить разные QOS для каждой создаваемой операции CKO, если вы не хотите использовать значение по умолчанию .utility.Если вы обнаружите, что часто делаете это со связанными операциями, я бы посоветовал взглянуть на CKOperationGroup и его свойство конфигурации по умолчанию - если вы установите QOS в конфигурации, оно переопределит значение по умолчанию в любом CKOperation с в группе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...