我正在尝试处理Cloudkit错误。我读了这篇文章:CloudKit - full and complete error handling example,但我有几个问题:
1.如果不设置.qualityOFService,为什么错误处理不起作用?正如文章中提到的,设置为.background?.userInitiated是否正确?另外,我是否必须为loadDataAgain()设置它
2.如何使接受错误和另一个参数的错误处理可重用(根据从中调用的视图控制器)?
@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)
}发布于 2018-10-12 19:55:56
对于您的第一个问题,请参阅建议未报告错误的this answer以了解较低的服务质量设置:
这是因为系统正在等待更好的网络条件,而如果您设置了
.default或.userInitiated,则系统希望得到“实时”响应
如果你看看the docs关于能源效率的内容,苹果似乎证实了这一点,他说
CKOperation是NSOperation类的子类。尽管NSOperation类的默认QoS级别为NSQualityOfServiceBackground,但CKOperation对象的默认QoS级别为NSQualityOfServiceUtility。在这个级别上,当您的应用程序不使用时,网络请求被视为可自由选择的。在iPhones上,启用低功耗模式时,会暂停任意操作。
如果您不需要默认的.utility,则需要为您创建的每个CKOperation显式设置不同的QOS。如果您发现自己经常使用相关操作执行此操作,我建议您查看CKOperationGroup及其default configuration property -如果您在配置中设置了CKOperation,它将覆盖组中任何QOS的默认值。
https://stackoverflow.com/questions/52776986
复制相似问题