访问 Alamofire 中的错误导致 EXC_BAD_ACCESS

Accessing the error in Alamofire causes EXC_BAD_ACCESS

在我的 iOS 应用程序中,我有一个带有文本字段的 UIVieController,它会在每次编辑值时发送请求。重点是显示从服务器作为 JSON 对象返回的用户建议。 我最初有所有 Alamofire 请求 运行 自由但为了减轻负载(即使这些请求是 非常 轻量级)我添加了

didSet {
    oldValue?.cancel()
}

到我的控制器的 modalRequest 属性,它存储当前请求。

但是现在,我的响应处理程序在尝试访问闭包中的错误时抛出 EXC_BAD_ACCESS(代码=1,地址=0x0)。代码如下:

@IBAction func textValueChanged(sender: AnyObject) {
    currentTextField = (sender as UITextField)

    if (currentTextField!.text != "") {
        modalRequest = Alamofire.request(.GET, "http://example.org/autocomplete/" + modalType.rawValue, parameters: ["term":currentTextField!.text]).responseJSON {(request, response, json, error) in
            if let error = error {
                NSLog("Error: \(error)")
                println(request)
                println(response)
            } else {
                let oldCount = self.suggestions.count
                self.suggestions.removeAll()
                let suggestionJSON = JSON(json!)
                for s in suggestionJSON.arrayValue {
                    self.suggestions.append(s["name"].stringValue)
                }
                self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic)
            }
        }
    } else {
        self.modalRequest?.cancel()
        self.suggestions.removeAll()
        self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}

奇怪和令人担忧的部分是,当我快速键入时,从而取消未完成的请求,一切都会迅速进行(双关语意),这意味着控制台将所有错误记录为已取消。但是,如果我输入的文本包含 space 并且之前的请求通过快速键入被取消,记录器会尝试打印错误但会抛出 EXC_BAD_ACCESS、,即使它处于可选绑定中!难道不应该确保值不为零,所以至少存在吗?

你遇到过这种情况吗?

感谢您的宝贵时间!

注意:删除该行当然有效,但我可能想在将来添加错误处理,这个错误真的很烦我

我认为您陷入了两种可能的竞争条件。

  1. 上一个modalRequest的deinit
  2. 自我的弱化/强化问题

下面应该解决这两个竞争条件。

@IBAction func textValueChanged(sender: AnyObject) {
    currentTextField = (sender as UITextField)

    if (currentTextField!.text != "") {
        modalRequest?.cancel()
        modalRequest = nil

        modalRequest = Alamofire.request(.GET, "http://example.org/autocomplete/" + modalType.rawValue, parameters: ["term":currentTextField!.text])
        modelRequest.responseJSON { [weak self] request, response, json, error in
            if let strongSelf = self {
                if let error = error {
                    NSLog("Error: \(error)")
                    println(request)
                    println(response)
                } else {
                    let oldCount = self.suggestions.count
                    self.suggestions.removeAll()
                    let suggestionJSON = JSON(json!)
                    for s in suggestionJSON.arrayValue {
                        self.suggestions.append(s["name"].stringValue)
                    }
                    self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic)
                }
            }
        }
    } else {
        self.modalRequest?.cancel()
        self.suggestions.removeAll()
        self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}

如果这最终奏效,那么我建议移动以下内容:

modalRequest?.cancel()
modalRequest = nil

变成willSet而不是didSet

willSet {
    modalRequest?.cancel()
}

为了继续我之前对 cnoon 回答的评论:我用 println() 替换了 NSLog() 瞧!有用!没有更多 EXC_BAD_ACCESS.

但是我不知道为什么访问不好。 NSLog 是不是太慢了,或者它没有复制值所以当它最终记录时它是零?我不知道...

EDIT :正如我在问题中所说,当查询包含 space 时,它 崩溃。 error.description 按原样添加到字符串中,包含 URL 字符串。在 URL 中编码的 space 是“%20”,因此 NSLog 将其解释为字符串格式化程序 %2,因此它会在 [=13] 中寻找第二个可选参数=] 当然, 不存在 !哈哈!因此,为了真正完美地修复它,我将这一行替换为:

NSLog("Error: %@", error)

现在是一个漂亮的日志,没有任何问题!这就是我复制一些默认代码的结果,这些代码结合了 Swift 字符串插值和 Objective-C 字符串格式!