使用NSNumberFormatter时EXC_BAD_ACCESS(code = 2)

时间:2015-05-12 13:40:35

标签: swift uiviewcontroller uilabel exc-bad-access iboutlet

我遇到了一个问题,我无法理解我的生活。我搜索了互联网,试图理解Swifts的EXC_BAD_ACCESS,但似乎没有任何帮助。

以下代码很长,但大多数时候评论都是了解相关项目所需的全部信息。

我有一个班级CalculatorController,其中包含以下相关方法和属性:

import UIKit    

class CalculatorController: UIViewController {

    // the actual `@IBOutlet` which is never accessed directly
    @IBOutlet private weak var _mainDisplay: UILabel!

    // an instance of `MainDisplayMicroController`
    // holds a reference to `_mainDisplay`
    // is used to manipulate `_mainDisplay` in a controlled way
    private var mainDisplay: MainDisplayMicroController!

    override func viewDidLoad() {
        super.viewDidLoad()

        // connects `mainDisplay` with `_mainDisplay`
        mainDisplay = MainDisplayMicroController(label: _mainDisplay)

        // sets `_mainDisplay`'s `text` property to "0"
        mainDisplay.content = .Number(0)

        //...
    }

    //...
}

为了以某种方式管理_mainDisplay,我创建了一个类MainDisplayMicroController,它一方面包含对UILabel本身的引用,另一方面包含对UILabel本身的引用。 hand包含方法和属性,它们对import UIKit class MainDisplayMicroController { // used to express what `label.text` is currently showing private enum DisplayState { case ShowingNumber case ShowingConstant case ShowingErrorMessage case Unknown } // holds the current state of what `label.text` is showing private var state = DisplayState.Unknown // used to pass different types of values in and out of this class enum ContentType { case Number(Double) case Constant(String) case ErrorMessage(String) case Unknown(Any?) } // holds the reference to the label which is being manipulated/managed private var label: UILabel? // makes `label`'s `text` property directly accessible, as `label` is `private` var text: String? { get { return label?.text } set { label?.text = newValue removeLeadingZeros() transformToInteger() } } // a property to allow controlled retrieval and manipulation of `label.text` // uses `ContentType` to make clear what the information in `label.text` is/ is supposed to be var content: ContentType { get { switch state { case .ShowingNumber: if let string = text { if let value = NSNumberFormatter().numberFromString(string)?.doubleValue { return .Number(value) } } case .ShowingConstant: if let symbol = text { return .Constant(symbol) } case .ShowingErrorMessage: if let message = text { return .ErrorMessage(message) } default: break } state = .Unknown return .Unknown(text) } set { switch newValue { case .Number(let value): text = "\(value)" state = .ShowingNumber removeLeadingZeros() transformToInteger() case .Constant(let symbol): text = symbol state = .ShowingConstant case .ErrorMessage(let message): text = message state = .ShowingErrorMessage case .Unknown(let thing): text = "Error: Passed unknown value: \(thing)" state = .ShowingErrorMessage } } } // removes the ".0" from `label.text`, if it is a whole number private func transformToInteger() { if state == .ShowingNumber { switch content { case .Number(let value): if round(value) == value { var doubleString = "\(value)" if doubleString.rangeOfString("e") == nil { dropLast(doubleString) dropLast(doubleString) } text = doubleString } default: break } } } // removes leading "0"s from `label.text` if they are redundant private func removeLeadingZeros() { if state == .ShowingNumber { switch content { case .Number(let displayedValue): content = .Number(displayedValue) default: break } } } //... }

执行操作
EXC_BAD_ACCESS

现在,当我运行代码时,我收到以下错误:

Error 1

从我在NSZombie上看到的内容,尝试在已发布对象上调用方法时经常会出现错误。我已尝试使用NSZombie来检查问题,但我没有找到任何内容(可能是因为我使用mainDisplay时无能)。

如果我试着按照逻辑发生的事情,我会得出以下结论:

  1. viewDidLoad()已在mainDisplay.content
  2. 中成功设置
  3. content被称为
  4. .Number的setter中,switch-statement执行text case
  5. stateremoveLeadingZeros()已成功设置
  6. content被称为
  7. switch-statement访问content的getter
  8. .ShowingNumber的getter中的switch语句执行NSNumberFormatter case
  9. if-statements解析为true,最后尝试评估EXC_BAD_ACCESS表达式
  10. 发生@IBOutlet
  11. 有谁知道为什么会这样?是否与我在另一个班级操纵NSNumberFormatter有关? 非常感谢任何帮助!

    以下是指向完整CalculatorControllerMainDisplayMicroController的链接。

    更新#1:

    @abdullah建议我尝试将MainDisplayMicroController表达式指向多个表达式。我仍然得到错误:

    Error 2

    更新#2:

    我删除了所有引用和外部类,使其尽可能简单,同时保持相同的功能 CalculatorModel中定义的所有方法和属性都已移至@IBOutlet 现在,这些方法和属性可以访问原始EXC_BAD_ACCESS(code=2),而不是对它的任何引用。

    但是当我尝试运行它时,我会在同一行代码中得到NSNumberFormatter 我只是非常困惑,因为它与奇怪的引用无关,或者对象过早被释放。

    以下是新CalculatorController的完整代码。

    更新#3:

    我删除了 node.Rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE); 行,将其更改为:

    Change from NSNumberFormatter

    现在我收到以下错误:

    New Error

    我认为代码存在一些基本问题,所以我要废弃它。但感谢所有的帮助,并尝试解决这个问题。

    更新#4:

    这是我在throw上为所有异常添加断点时得到的结果:

    Exception

4 个答案:

答案 0 :(得分:6)

我真的没有看到任何可能导致崩溃的行。我建议你做以下事情:

  1. 进行干净的构建(清理,核对您的派生数据文件夹,然后构建)并查看崩溃是否仍然存在
  2. 如果崩溃仍然存在,set a breakpoint on throw for all exceptions以查看callstack中的哪个操作导致崩溃,并从那里获取

答案 1 :(得分:0)

@WarrenBurton正在努力。

从你的大班上撞掉你的线路并在操场上运行它并且工作正常:

let string = "1.213"
if let value = NSNumberFormatter().numberFromString(string)?.doubleValue 
{
  println("value = \(value)")
}

显示结果

  

值= 1.213

你的变量在哪里"字符串"你班上定义的?

答案 2 :(得分:0)

请注意,字符串是蓝色的,就像关键字一样,而不是黑色,就像其他局部变量一样。

我尝试使用局部变量string ==> MyString的 只是为了确定。

答案 3 :(得分:0)

Just&#cu; cuz我看到同样的事情,并注意到没有人评论过你的上一次编辑(也许这个问题的Googler同事有一天会看到这个):

对于我们两种情况,问题都是无限递归 - 我们无限地从自身调用一个方法。这就是错误。 A崩溃的含义是红鲱鱼。