swift - 处理 cloudkit 错误时未捕获的异常“NSInvalidArgumentException”
问题描述
我的应用程序因以下错误而崩溃,我正在尝试复制它但我不能,所以任何人都可以提供一些关于出了什么问题的见解?
class ViewController: UIViewController {
//all the usual class methods here
@objc func getData() {
self.array = []
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: “Product”, predicate: predicate)
let queryOperation = CKQueryOperation(query: query)
queryOperation.resultsLimit = 5
queryOperation.qualityOfService = .userInitiated
queryOperation.recordFetchedBlock = { record in
self.array.append(record)
}
queryOperation.queryCompletionBlock = { cursor, error in
if error != nil{
cloudkitHelper.request(error: error!, viewController: self). //this line causes the crash
}
else{
if cursor != nil {
self.askAgain(cursor!)
}
}
OperationQueue.main.addOperation {
self.tableView.reloadData()
}
}
Database.share.publicDB.add(queryOperation)
}
func askAgain(_ cursor: CKQueryOperation.Cursor) {
let queryOperation = CKQueryOperation(cursor: cursor)
queryOperation.resultsLimit = 5
queryOperation.recordFetchedBlock = {
record in
self.array.append(record)
}
queryOperation.queryCompletionBlock = { cursor, error in
if error != nil{
cloudkitHelper.request
}
else{
if cursor != nil {
self.askAgain(cursor!)
}
}
OperationQueue.main.addOperation {
self.tableView.reloadData()
}
}
Database.share.publicDB.add(queryOperation)
}
}
class cloudkitHelper: ViewController{
static func request( error:Error, viewController:ViewController) {
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.getData), 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.getData), 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.getData), userInfo: nil, repeats: false)
}
}
}
2018-10-17 19:54:41.335517+0100 cloudkitApp[6011:1308502] +[cloudkitApp.cloudkitHelper getData]:无法识别的选择器发送到类 0x103879c28 2018-10-17 19:54:41.407939+010080500cloudkitApp[60112] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“+ [cloudkitApp.cloudkitHelper getData]:无法识别的选择器发送到类 0x103879c28”
解决方案
请阅读错误信息。
它说没有选择器getData
是cloudkitHelper
真的。请CloudkitHelper
根据命名约定命名,并表明您正在调用一个类方法。
getData
属于ViewController
并且(目标)self
代表CloudkitHelper
该类。
Timer
将行更改为
Timer.scheduledTimer(timeInterval: retryInterval!, target: viewController, selector: #selector(getData), userInfo: nil, repeats: false)
而不是一个子类和ViewController
一个extension
实例方法更合理。我删除了冗余代码并使用了基于块的Timer
API
extension ViewController {
func request( error:Error) {
if let ckerror = error as? CKError {
switch ckerror.code {
case .requestRateLimited, .zoneBusy, .limitExceeded:
let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as! TimeInterval
Timer.scheduledTimer(withTimeInterval: retryInterval, repeats: false) { _ in
DispatchQueue.main.async {
self.getData()
}
}
default: break
}
}
}
}
推荐阅读
- visual-studio - 在 Visual Studio 中删除行而不更改剪贴板
- javascript - 序列化列表
在 C# 中并将其反序列化为 js 数组 - java - 什么是java库文件
- python - pytorch nn.Sequential(*list) TypeError: list is not a Module subclass
- javascript - 复选框切换器 VUE JS
- java - 如何从组件中注入 ApplicationContext?
- angular - 使用来自 API 的数据填充编辑表单复选框 - Angular
- java - 如何在 2d ArrayList 中找到对角线元素的总和?
- sql-server - 选择语句中的 SQL 死锁
- reactjs - 如何在 React 中逐行读取磁盘中的大 csv 文件?