为方便起见,可失败的初始化程序失败
Posted
技术标签:
【中文标题】为方便起见,可失败的初始化程序失败【英文标题】:Failable initializer for convenience init fails 【发布时间】:2016-10-23 01:46:22 【问题描述】:我有以下 NSDate
扩展初始化程序来从给定字符串创建 NSDate
对象。
extension NSDate
convenience init(string: String)
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = dateStringFormatter.dateFromString(string)
self.init(timeInterval:0, sinceDate:date!)
但是对self.init
方法的调用会强制解开不安全的date
变量。所以我试图让它成为一个失败的初始化器。
extension NSDate
convenience init?(string: String)
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let date = dateStringFormatter.dateFromString(string) else
return nil
self.init(timeInterval:0, sinceDate:date)
但它在nil
返回行出现EXC_BAD_ACCESS 错误而崩溃。我不知道为什么。
我在这里做错了什么?
【问题讨论】:
我知道这很疯狂,但是在警卫内部添加一个毫无意义的self.init
调用(没关系,只要它成功)。即使我返回 nil,我也会因为没有完全初始化 self 而出现编译器错误。
@LouFranco 哇,成功了!这是一个 Swift 错误还是我们应该这样做?
我无法在 ios 模拟器中重现该问题,您的代码对我来说很好。
@MartinR 我在设备上运行此代码。我正在使用 Xcode 7.3。
奇怪,在我的 iOS 9 设备上也可以使用。
【参考方案1】:
如果您使用extension
,您需要在返回 nil 之前初始化“超类”。见
convenience init?(string: String)
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let date = dateStringFormatter.dateFromString(string) else
self.init()
return nil
self.init(timeInterval:0, sinceDate:date)
docs 状态
类的所有存储属性(包括该类从其超类继承的任何属性)都必须在初始化期间分配一个初始值。
【讨论】:
随着 Swift 2.2/Xcode 7.3 的改变。来自developer.apple.com/library/prerelease/content/documentation/…:在类内部,允许在初始化所有存储的属性并调用 super.init() 之前退出可失败 (init?()) 或抛出 (init() throws) 的指定初始化程序。这种行为使指定初始化器与便利初始化器更加一致。 在执行 self.init() 委托之前,便利初始化程序也可能失败。 否则代码不应编译,也不会因运行时异常而崩溃。 @MartinR 我认为这不适用于extension/inheritance
。
如果代码不满足初始化要求,则不编译(但OP的代码编译)。以上是关于为方便起见,可失败的初始化程序失败的主要内容,如果未能解决你的问题,请参考以下文章