我的应用程序崩溃并出现以下错误,我正在尝试复制它,但是我不能,所以有人可以提供一些有关出了什么问题的见解吗?
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 + 0100 cloudkitApp [6011:1308502] ***由于未捕获而终止应用程序 异常“ NSInvalidArgumentException”,原因: '+ [cloudkitApp.cloudkitHelper getData]:无法识别的选择器已发送至 类别0x103879c28'
答案 0 :(得分:1)
请阅读错误消息。
它表示getData
中没有选择器cloudkitHelper
,这是事实。请根据命名约定将其命名为CloudkitHelper
,并表示您正在调用 class 方法。
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
}
}
}
}