The problem is that since Swift doesn’t think this value can be nil, it’s not trivial to check.
It says the non-optional value shouldn’t be compared to nil, and that it’s always false. But at run time, the nil is detected, and we print the statement.
What’s interesting here is that the argument to the bridge function is an
Optional<NSCalendar>. The static method, by its signature, accepts nil. What’s happening then? In this case, The culprit for the crash and what saves us from unexpected behavior later on is a force unwrap. Though the value that’s actually passed in to the function is
Optional<NSCalendar>.some(nil), which is still not a valid value and we’re still in undefined behavior territory, so it’s pleasantly surprising that a force unwrap catches this case.
Having the the compiler automatically check and assert that nonnull Objective-C types returned by Objective-C methods are indeed present would be fantastic, whether for debug builds or as an independent flag.
To make sure we’re all on the same page: returning
nonnullimported API is full-on, demons-flying-out-of-your-nose undefined behavior. There’s no guarantee that it will do what you saw.
Unfortunately, it’s rather easy to get the annotations wrong, and even Apple does this. For example, the
SecTransformExecute() calls can return
NULL in Objective-C, but Swift acts as if they can’t fail. I filed a bug about about this, which Apple recently said was so old that they wanted to close it and have me open a new one. Meanwhile, I’m able the work around the issue because these two APIs have a separate error pointer that can be examined. Without that, I think you would need an Objective-C wrapper to safely detect whether an error has occurred.
The SecTransform API is effectively deprecated, and has been so since 10.12. Unfortunately it’s taken a while for us to formally deprecate it (r. 25183002).