Swift compiler errors demand DateFormatter() be unwrapped. Or not.

When I instantiate a DateFormatter, the compiler says the result is optional, and I must unwrap it.

When I do, the compiler says the result is not optional, and I must remove all those !'s and ?'s.

Should be right

let _yyyy_mm_dd: DateFormatter = {
    let retval = DateFormatter()
    retval.dateFormat = "yyyy-MM-dd"
    return retval
}()

extension Date {
    public var ymd: String {
        _yyyy_mm_dd.string(from: self)
    }
}

This has happened with a couple of other types, but DateFormatter is easiest to demonstrate.

(Apple has from time to time warned that leading underscores are sacred to its frameworks, but in this case, renaming the formatter yyyy_mm_dd had no effect.)

Without the bangs (!), as shown above, swiftc flags a syntax error::

error-support.swift:83:5 Value of optional type 'DateFormatter?' must be unwrapped to refer to member 'dateFormat' of wrapped base type 'DateFormatter'

- Chain the optional using '?' to access member 'dateFormat' only for non-'nil' base values
- Force-unwrap using '!' to abort execution if the optional value contains 'nil'

The compiler offers FIXMEs which do exactly as the message suggests.

Let's try putting a bang after the initializer:

let retval = DateFormatter()!

Now I get

error-support.swift:82:33 Cannot force unwrap value of non-optional type 'DateFormatter'`

I invoke DateFormatter twice, with the same results. Attempting to unwrap the non-optional DateFormatter is a straightforward syntax error. But not unwrapping is flagged as an error, too (though it's non-fatal).

This is in a project of about 6500 lines of Swift (counted by cloc, no comments). It works as expected in a playground.


Paradox

Sometimes these errors go away spontaneously. Sometimes they fail the build. Mostly, the build succeeds anyway; the false alarms disappear, then "Build Succeeded," then the error flags reappaer, but do not interfere with execution.

I've done ProductClear All Issues. I've cleaned the Build Folder repeatedly. A few times I deleted the build directory. All remove the flags. but the next build command shows both success and the error flags.


Meditiation

DateFormatter is an immediate subclass of NSObject, and has no (visible) override for init(). In principle, one could argue that if [self init] could fail, then so should a direct descendant. There is a universe in which init() would be failable, but not this one. It's supposed to be special-cased.


Plea

Can you suggest a way to put a stop to these false-alarm errors? We're used to noisy log entries, occasionally nuisance warnings. There shouldn't be nuisance errors.


Environment

Xcode 14.2 (14C18)
macOS 13.2 Ventura
MacBook Pro 16" (2021), M1.Pro
Memory pressure < 35%, 550 GB free, CPUs maybe above 250% for an instant or two.

Replies

I tested the following in playground. No error.

let _yyyy_mm_dd: DateFormatter = {
    let retval = DateFormatter()
    retval.dateFormat = "yyyy-MM-dd"
    return retval
}()

extension Date {
    public var ymd: String {
        _yyyy_mm_dd.string(from: self)
    }
}

print(Date().ymd)

Could you show precisely the context in which the problem occurs ?

Nor did I have any problem in a playground, whether in Xcode or in Playgrounds (iPad). I know that the least I could do is to provide a minimal example, and much sooner than this,, but this very code is part of a 5000 LoC project that has more than one deadline this week. This isn't a case of OP-stopped-responding.

Nor did I have any problem in a playground, whether in Xcode or in Playgrounds (iPad)

So, where do you have a problem ?