3
votes

I have the following NSDate extension initializer to create a NSDate object from a given string.

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!)
    }
}

But the call to self.init method force unwraps the date variable which is not safe. So I'm trying to make this a failable initializer.

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)
    }
}

But it crashes with a EXC_BAD_ACCESS error at the nil returning line. I can't figure out why.

What am I doing something wrong here?

1
I know this is crazy, but add a pointless self.init call inside the guard (doesn't matter what, as long as it succeeds). I've had compiler errors for not fully initing self even if I return nil. - Lou Franco
@LouFranco Whoa, that worked! Is this a Swift bug or are we supposed to do this? - Isuru
I cannot reproduce the problem in the iOS Simulator, your code works fine for me. - Martin R
@MartinR I was running this code on a device. I'm using Xcode 7.3. - Isuru
Strange, works on my iOS 9 device as well. - Martin R

1 Answers

-1
votes

If you use extension you need to initialize the "superclass" before returning nil. See

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)
}

The docs states

All of a class’s stored properties—including any properties the class inherits from its superclass—must be assigned an initial value during initialization.