【问题标题】: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 设备上也可以使用。

标签: ios swift initialization extension-methods failable


【解决方案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的代码编译)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 2012-09-10
  • 1970-01-01
相关资源
最近更新 更多