最奇怪的事情。我有两种方法以完全相同的方式使用可选的枚举。在设备和模拟中,一个功能始终有效。但是,第二种方法仅适用于模拟器,而有时适用于设备。我很确定它“何时”起作用与我所做的测试值无关。例如,我总是先用nil值调用方法,有时只会崩溃。
错误是EXC_ARM_BREAKPOINT,没有打印消息,堆栈跟踪没有帮助。调试器甚至在检查nil之后将可选的值显示为“Some”,这很奇怪,因为我无法打印它(在尝试时崩溃)。
失败的代码:
class LevelElevenState: GameState {
init(count: Int, var goalNumber: GameNumber?) {
super.init(stateType: .Normal)
self.transition = {
(actionDone: GameAction) -> GameState? in
switch actionDone {
case .Pressed(let number):
if goalNumber == nil { //FAILS HERE
goalNumber = number //OR HERE
}
if goalNumber == number {
self.delegate?.switchIndicators(true, lights: [GameNumber(rawValue: count)!])
if count < 5 {
let direction = GameDirection(rawValue: Int(arc4random()) % 2)!
let amount = Int(arc4random_uniform(98)) + 1
var nextRaw = number.rawValue
switch direction {
case .Up:
nextRaw = (nextRaw + amount) % 5
case .Down:
nextRaw = ((nextRaw - amount) % 5) + 5
}
let nextNumber = GameNumber(rawValue: nextRaw)
let phrase = "\(direction), \(amount)"
self.delegate?.speakPhrase(phrase)
return LevelElevenState(count: count + 1, goalNumber: nextNumber)
} else {
return GameState.goal()
}
}else {
return GameState.mistake()
}
default:
return nil
}
}
}
}
class LevelEleven: GameStateLevel, GameStateLevelDelegate {
override init() {
super.init()
levelDelegate = self
index = 10
}
func initialState() -> GameState {
return LevelElevenState(count: 1, goalNumber: nil)
}
}
以下代码永远不会崩溃。我个人认为没有区别。
class LevelSevenState: GameState {
var count = 0
init(goal: Int, var goalNumber: GameNumber?) {
super.init(stateType: .Normal)
self.transition = {
(actionDone: GameAction) -> GameState? in
switch actionDone {
case .Pressed(let number):
if goalNumber == nil {
goalNumber = number
}
if goalNumber == number {
self.count++
if self.count == goal {
if let indicator = GameNumber(rawValue: goal) {
self.delegate?.switchIndicators(true, lights: [indicator])
}
if goal < 5 {
return LevelSevenState(goal: goal + 1, goalNumber: goalNumber)
} else {
return GameState.goal()
}
}else {
return nil
}
}else {
return GameState.mistake()
}
default:
return nil
}
}
}
}
class LevelSeven: GameStateLevel, GameStateLevelDelegate {
override init() {
super.init()
levelDelegate = self
index = 6
}
func initialState() -> GameState {
return LevelSevenState(goal: 1, goalNumber: nil)
}
}
enum GameNumber: Int {
case One = 1
case Two = 2
case Three = 3
case Four = 4
case Five = 5
init?(myRaw: Int) {
if let fromRaw = GameNumber(rawValue: myRaw) {
self = fromRaw
}else {
return nil
}
}
init(color: GameColor) {
switch color {
case .Blue:
self = .One
case .Green:
self = .Two
case .Yellow:
self = .Three
case .Orange:
self = .Four
case .Red:
self = .Five
}
}
}
答案 0 :(得分:1)
我发现了问题。调试如此困难的原因是错误与我的想法无关。 XCode打破了错误的界限。这是造成错误的一行:
Int(arc4random()) % 2
我不确切地知道为什么会迅速崩溃,但这绝对是它。如果有人对这个问题有任何见解,我会很乐意接受一个解决这个问题的答案。
答案 1 :(得分:1)
是的,那是崩溃的Int(arc4random())
。原因是arc4random()
返回UInt32
,可能(随机!)超过Int.max
并导致Int(...)
崩溃 - 正如已解答here。
有很多方法可以避免这种情况,例如,您可以先计算余数,然后将其传递给Int(...)
:
Int(arc4random() % 2)
或者您可以使用
Int(arc4random_uniform(2))
确保Int(...)
的参数在限制范围内!
干杯)