为方便起见,可失败的初始化程序失败

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的代码编译)。

以上是关于为方便起见,可失败的初始化程序失败的主要内容,如果未能解决你的问题,请参考以下文章

带有可选参数的可失败的便利初始化器

使用 SwiftyJSON 的 Swift 可失败初始化器

使用 SpringBoot 懒惰初始化角色集合失败

什么情况下电脑会提示初始化程序失败?

急!!NVIDIA安装程序失败

可失败构造器(Failable Initializers)