首页 > 解决方案 > 处理 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”

标签: swift

解决方案


阅读错误信息。

它说没有选择器getDatacloudkitHelper真的。请CloudkitHelper根据命名约定命名,并表明您正在调用一个方法。

getData属于ViewController并且(目标)self代表CloudkitHelper该类。

Timer将行更改为

Timer.scheduledTimer(timeInterval: retryInterval!, target: viewController, selector: #selector(getData), userInfo: nil, repeats: false)

而不是一个子类和ViewController一个extension实例方法更合理。我删除了冗余代码并使用了基于块的TimerAPI

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

推荐阅读