我在Swift中使用可用的初始化程序进行了一次奇怪的崩溃。我很确定这是Swift中的一个错误,但我想我会快速发帖,看看我是否遗漏了一些明显的东西。
我正在使用CloudKit编写应用程序并为CKRecord添加了一个新的便利初始化程序:
extension CKRecord {
convenience init?(cloudInfo: NSData?) {
guard let info = cloudInfo else { return nil }
self.init(coder: NSKeyedUnarchiver(forReadingWithData: info))
}
这只使用我使用CKRecord的encodeSystemFieldsWithCode:
方法创建的归档数据来创建CKRecord
实例。我以前只是在班上有一个方法来做同样的事情而且工作正常。
当我像这样调用这个初始化程序时:
let record: CKRecord
if let rec = CKRecord(cloudInfo: self.cloudInfo) {
record = rec
} else {
record = CKRecord(recordType: "Item", recordID: CKRecordID(recordName: self.id))
}
当我拨打电话时,我发生了撞车事故。如果我为cloudInfo
传递nil或值,则无关紧要。单步执行代码时,崩溃似乎发生在从init调用返回并返回调用者之间。例如,如果我传递nil
并进入guard
中似乎有效的init
语句,但一旦我离开它,我就会崩溃。
我已经尝试摆脱guard
并使用简单的if let
构造,但结果相同。而且,我刚刚从nil
返回init
而没有任何其他代码,而且还会崩溃。
我已经完成了常规:清理构建文件夹,重新启动等等。
顺便说一下,“崩溃”我的意思是我在呼叫站点获得EXC_BAD_ACCESS (code=1, address=0xfffffffc)
。
有没有人有任何想法?也许这是我想念的显而易见的事情。
感谢。
答案 0 :(得分:3)
根据 Swift编程语言(Swift 2.1)一书,
但是,对于类,只有在该类引入的所有存储属性都已设置为初始值并且已进行任何初始化程序委派之后,可用的初始化程序才会触发初始化失败。
取自here。
您无法扩展具有存储属性的现有类,因此满足第一个要求。但是为了满足第二个要求,您必须像下面的代码一样委托初始化过程:
extension CKRecord {
convenience init?(cloudInfo: NSData?) {
guard let info = cloudInfo else {
self.init(coder: NSKeyedUnarchiver(forReadingWithData: NSData()))
return nil
}
self.init(coder: NSKeyedUnarchiver(forReadingWithData: info))
}
}
答案 1 :(得分:0)
实际上在Swift 3中,似乎存在来自Swift 2的错误和回归:returning nil from a failable intializer crash the runtime。