-4

One day, the app worked. The next day I updated to Xcode 11 and now the app crashes with "unexpectedly found nil" on line 27 (when executing line 15) in the picture.

I asked my co-worker who doesn't yet have Xcode 11, and his doesn't crash. we are on the same branch/commit...everything.

Any advice? any way around this?

My code:

// ticket.timeOrdered == "2019-10-03 22:54:57 +0000"

let ticketDate = ticket.timeOrdered.asCrazyDate.timeIntervalSince1970

extension String {

    var asCrazyDate: Date {
        let dateFormatterGet = DateFormatter()
        dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
        dateFormatterGet.timeZone = .current
        return dateFormatterGet.date(from: self)!
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ungraceful
  • 67
  • 1
  • 9
  • 2
    Possibly this: https://stackoverflow.com/questions/40692378/dateformatter-doesnt-return-date-for-hhmmss – Martin R Oct 03 '19 at 21:25
  • 1
    BTW - there is no need at all for your `asCrazyDate` method. Simply fix `getDate()` by eliminating the unnecessary use of string interpolation. – rmaddy Oct 03 '19 at 21:40
  • the purpose of this question was why does it work on xcode 10 but not xcode 11. the code I showed was a refactored "summary" of what was happening. I just uninstalled Xcode 11 and reinstalled Xcode 10.3. Everything works fine now. – Ungraceful Oct 03 '19 at 22:48
  • `"yyyy-MM-dd HH:mm:ss Z"` would work. But set your `locale`, too. – Rob Oct 03 '19 at 23:15
  • Possible duplicate of [What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – Cristik Oct 04 '19 at 18:13

1 Answers1

3

The date format string is incorrect. The +zzzz is not an acceptable format. See the timezone related sections of the table in Date Format Patterns. The + shouldn’t be there. And zzzz is for long descriptions of the time zone (e.g. “Pacific Daylight Time”). You can verify this by using the same formatter to build a string from Date() and you’ll see that it’s not resulting in the +0000 like you might have expected.

The latest SDK’s date formatter is no longer as forgiving regarding these sorts of format string errors as the previous versions were. But rather than reverting your Xcode version, you really should just fix that date format string. For example, you could use Z instead of +zzzz, which will correctly interpret the +0000 (or whatever) as the time zone portion of the string.


A few other suggestions, if you don’t mind:

  1. You don’t need asCrazyDate in this example. There’s no point in getting a date, using string interpolation to build the string representation, and then using a formatter to convert the string back to a date (which you originally started with). You can just use the Date directly:

    func getDate() -> TimeInterval {
        return Date().timeIntervalSince1970
    }
    
  2. Date formatters are notoriously computationally intensive to create, and if you’re using this computed property a lot, that can really affect performance. It’s better to instantiate date formatters once, if possible.

  3. If you’re trying to build some invariant date string for some reason, it’s better to use something like ISO8601DateFormatter. So don’t build your date strings using string interpolation, and don’t build your own formatter.

    let formatter = ISO8601DateFormatter()
    
    let now = Date()
    let string = formatter.string(from: now) // not "\(now)"
    
    let date = formatter.date(from: string)
    
    print(now, string, date)
    
  4. If you’re stuck with this date format (perhaps you’ve already stored dates using this string format), you can use the custom dateFormat string, if you must. But as Technical Q&A 1480 suggests, you might want to set the locale (and I’d suggest setting the timeZone, too, so your date strings are comparable).

    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Very informative, thank you! the getDate function was just to show stack overflow a shortened version of what I was trying to accomplish, but in retrospect was a bad example to use. I had no idea DateFormatters were expensive to use (frankly I don't even know how one would figure that out) I'll look at it more carefully and try some of your suggestions for ways around using my custom formatter so much. Thanks again – Ungraceful Oct 03 '19 at 23:24
  • See “Performance Strategies” section of [iOS App Performance: Responsiveness](https://developer.apple.com/videos/play/wwdc2012/235/) regarding this performance issue. It’s dated, focused on Objective-C and `NSDateFormatter`, but the issues are the same with `DateFormatter`. – Rob Oct 03 '19 at 23:35