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 Product → Clear 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.