I'm writing an extension for NSDate which provides some failable initializers. The end goal here is to get a date time string from an API and parse it into an NSDate, e.g.
let createdAt = NSDate(apiDateTimeString: "2016-03-29T18:33:49+06:00")
let createdAt = NSDate(apiDateTimeString: "2016-03-29T18:33:49.730+06:00")
The date time string can take one of 2 formats:
yyyy-MM-dd'T'HH:mm:ssZZZZZ
yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ
Here is what the extension looks like:
import Foundation
public extension NSDate {
// MARK: Custom Initializers
public convenience init(date: NSDate) {
self.init(timeInterval: 0.0, sinceDate: date)
}
public convenience init?(dateString: String, formatString: String) {
let formatter = NSDateFormatter()
formatter.dateFormat = formatString
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
if let date = formatter.dateFromString(dateString) {
self.init(date: date)
} else {
return nil
}
}
public convenience init?(apiDateTimeString: String?) {
guard let dateString = apiDateTimeString else {
return nil
}
if NSDate(dateString: dateString, formatString: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") != nil {
self.init(dateString: dateString, formatString: "yyyy-MM-dd'T'HH:mm:ssZZZZZ")
} else {
self.init(dateString: dateString, formatString: "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ")
}
}
}
When I try to use this, it get an EXC_BAD_ACCESS
at if NSDate(dateString: dateString, formatString: "yyyy-MM-dd'T'HH:mm:ssZZZZZ") != nil
Any help figuring out why this isn't working is appreciated.
EDIT: I forgot to add: this worked with Swift 2.1, and quit working with Swift 2.2
This is an issue in Swift 2.2. For more information, see SR-704: EXC_BAD_ACCESS on returning nil from a failable initializer of NSObject subclass. Looks like it was fixed in the mainline branch, but didn’t make it into the final Swift 2.2 release. Expect it to be fixed in the next point update.
As a temporary workaround, make sure to to always initialize the object before returning nil
from a failable initializer (or throwing from a throwing initializer). That is, insert self.init()
before every return nil
statement.
Edit: This issue has been fixed in Swift 2.2.1/Xcode 7.3.1. It should no longer be necessary to initialize the instance before returning nil
.