Mar*_*sel 11 exc-bad-access uiviewcontroller uilabel iboutlet swift
我遇到了一个问题,我无法理解为我的生活.我搜索了互联网,试图了解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)
//...
}
//...
}
Run Code Online (Sandbox Code Playgroud)
为了以_mainDisplay某种方式进行管理,我创建了一个类MainDisplayMicroController,它一方面包含对UILabel自身的引用,另一方面包含对以下内容执行操作的方法和属性UILabel:
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
}
}
}
//...
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行代码时,我收到以下错误:

从我读过的内容来看EXC_BAD_ACCESS,在尝试调用已发布对象上的方法时经常会出现错误.我试过NSZombie用来检查问题,但我没有找到任何东西(可能是因为我使用时无能NSZombie).
如果我试着按照逻辑发生的事情,我得出以下结论:
mainDisplay 已成功设置 viewDidLoad()mainDisplay.content 叫做contentsetter中,switch-statement执行.Numbercasetext并state成功设置removeLeadingZeros() 叫做content的gettercontent'getter中的switch语句执行.ShowingNumber大小写NSNumberFormatter表达式EXC_BAD_ACCESS发生有谁知道为什么会这样?是否与我操纵@IBOutlet另一个班级有关?
任何帮助是极大的赞赏!
这里是完整CalculatorController和MainDisplayMicroController.
正如@abdullah建议我尝试将NSNumberFormatter表达式指向多个表达式.我仍然得到错误:

我删除了所有引用和外部类,使其尽可能简单,同时保持相同的功能.已
定义的所有方法和属性MainDisplayMicroController已移至CalculatorModel.
这些方法和属性现在可以访问原始文件@IBOutlet,而不是对它的任何引用.
但是当我试图运行它时,我会得到EXC_BAD_ACCESS(code=2)相同的代码.
我只是非常困惑,因为它与奇怪的引用无关,或者对象被释放得太快了.
这是新的完整代码CalculatorController.
我删除了该NSNumberFormatter行,将其更改为:

现在我收到以下错误:

我假设代码存在一些基本问题,所以我要废弃它.但感谢所有的帮助,并尝试解决这个问题.
这是我在throw上为所有异常添加断点时得到的结果:

我真的没有看到任何可能导致崩溃的行.我建议你做以下事情:
@WarrenBurton 正在做一些事情。
把你的大班崩溃的线拿出来,在操场上运行它,它工作得很好:
let string = "1.213"
if let value = NSNumberFormatter().numberFromString(string)?.doubleValue
{
println("value = \(value)")
}
Run Code Online (Sandbox Code Playgroud)
显示结果
值 = 1.213
你的变量“string”在你的类中定义在哪里?
| 归档时间: |
|
| 查看次数: |
3516 次 |
| 最近记录: |