我正在尝试处理Cloudkit错误。我读了这篇文章:CloudKit - full and complete error handling example 但是我有几个问题:
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)
}
答案 0 :(得分:0)
关于您的第一个问题,请参见this answer,该报告建议不因服务质量较低而报告错误:
这是因为[the]系统正在等待更好的网络状况,而[if]设置
.default
或.userInitiated
时,系统期望“实时”响应
如果您查看the docs的能源效率,苹果似乎肯定了这种方法,
CKOperation是NSOperation类的子类。尽管NSOperation类的默认QoS级别为NSQualityOfServiceBackground,但CKOperation对象的默认QoS级别为NSQualityOfServiceUtility。在此级别,当您的应用未使用时,网络请求将被视为可酌情处理的。在iPhone上,启用低功耗模式会暂停任意操作。
如果您不想使用默认的.utility
,则需要为创建的每个CKOperation显式设置一个不同的QOS。如果您发现自己经常通过相关操作执行此操作,建议您查看CKOperationGroup
及其default configuration property-如果在配置中设置了QOS,它将覆盖所有{{1 }}。