我有这堂课:
class IdentifiableModel: KeyValueModel {
class var OBJECT_ID: String { return "object_id" }
override init() {
super.init()
self.setRandomId() // Breakpoint 1 HERE
}
override init(dict: Dictionary <String, String>) {
super.init(dict: dict)
self.setRandomId()
}
var objectId: String?
func getObjectId() -> String? {
return nil
}
func setObjectId(value: String) {
}
private func setRandomId() {
if getObjectId() == nil { // Breakpoint 2 HERE
setObjectId("\(Int(arc4random()))")
}
}
}
实例化变量
var obj = IdentifiableModel()
重现的步骤:
1)暂停断点1
2)继续断点2
3)多次踩踏。
在大多数情况下,程序将在断点2的行上显示EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP)
。
答案 0 :(得分:3)
你的问题在于:
Int(arc4random())
arc4random()返回一个UInt32-a unsigned 32位整数。如果您编译32位平台的上述代码,比如iPhone 4,那么您尝试填充它的Swift Int将是一个32位签名的整数,一个Int32。 (这也是@Pavi无法在操场上重现问题的原因;操场将是64位。)
所以,在32位平台上,有时 - 大约一半的时间,实际上arc4random()将返回一个对你的Int构造函数来说太大的值,你就会得到一个库中的断言失败(EXC_BAD_INSTRUCTION是这个的正常线索;断言失败故意将错误的指令抛到处理器上以暂停一切。)
你基本上决定是否根据投掷硬币而崩溃:)
因此,您需要为您的ID使用特定的,足够大的整数类型(UInt32应始终有效,因为它是arc4_random的返回类型),或者限制随机数生成器的结果,例如,使用arc4random_uniform生成特定范围内的数字。
事实上,你可以通过删除不必要的强制转换来解决问题:
setObjectId("\(arc4random())")
......但当然,它取决于你实际上要做的事情,以及为什么......