In Apple's blog on nullability, they mention this:
"...in Swift there’s a strong distinction between optional and non-optional references, e.g. NSView vs. NSView?, while Objective-C represents boths of these two types as NSView *. Because the Swift compiler can’t be sure whether a particular NSView * is optional or not, the type is brought into Swift as an implicitly unwrapped optional, NSView!"
Does that mean previously when declaring Objective-C methods as returning implicitly unwrapped optional in Swift, it can in fact crash (since some of the methods declared with implicitly unwrapped optional may return nil)? Or does Apple make sure only those Objective-C methods that absolutely do not return nil get declared as implicitly unwrapped optional?
Apple's frameworks aren't anything special. In the beginning, everything (every object) you used from Objective-C in Swift was an implicitly unwrapped optional. That was because every pointer in Objective-C could possibly return
nil
.In fact, even in the era of Objective-C nullability annotations, it's not entirely impossible that a method annotated as
nonnull
could returnnil
. Objective-C doesn't enforce the nullability rules, it merely provides a means for annotating your code so that it should be safer to use from Swift. In the case of Apple's frameworks, I'd wager it's a pretty safe bet that you won't have this problem. Or if you do, the next version of Xcode will fix it.But again, there's nothing special about implicitly unwrapped optionals coming from Objective-C libraries and frameworks. The only thing that an implicitly unwrapped optional tells you is that the framework author has not made the effort to annotate their library yet (you can't leave implicitly unwrapped optionals in an annotated library). And yes, these implicitly unwrapped options can be
nil
and they can crash your application.In the case of Apple, if for some reason, you're using say Xcode 7 and Xcode 6 on different projects, if you take something which Xcode 7's update annotations have declared as non-optional, then assuming the implicitly unwrapped optional version in Xcode 6 will never be
nil
might work out. But if you take something that is an optional in Xcode 7, assuming the implicitly unwrapped version from Xcode 6 will never benil
probably has a decent likelihood of crashing your app.Ultimately, in Swift, our use of implicitly unwrapped optionals should be few and far between. The primary use of implicitly unwrapped optionals should mostly be reserved for class properties which cannot be set before the class initialization has returned (for example,
@IBOutlets
in a view controller). Otherwise, they're prone to being the source of numerous "Unexpectedly found nil" questions here on Stack Overflow.To the question of "Why return an implicitly unwrapped optional rather than an optional?", a few points...
First, that's a language design question. I'm not on the Objective-C or Swift language design team and it's unlikely that anyone from those teams will stop by and answer that question...
Second, that's how the languages are designed to interoperate. Any Objective-C file which has not had nullability annotations added will be treated as if everything is an implicitly unwrapped optional in Swift.
Third, the reason for implicit optionals is it reduces a lot of the verbosity of
if let
etc statements that optional would require, while not guaranteeing that the variable is actuallynon-nil
. Most of the reason for this is probably because you figure most of these methods actually never returnnil
.Fourth, if you know which ones have a chance to be
nil
and which ones don't, you can actually go ahead and write your Swift code in a way which handles both making assumptions about which way the Objective-C code will be annotated.For example, with an implicitly unwrapped optional, of course, you can treat it like a non-optional and remove some of the minor verbosity involved with unwrapping.
Additionally, with an implicitly unwrapped optional, if you think it might be
nil
, all of the optional unwrapping stuff can still work with it.Example:
If we assumed them all as optionals, the second example wouldn't work
If we assumed them as non-optionals, the first example wouldn't work.
Implicitly unwrapped optionals allows the freedom for the Swift developer to treat them as either if they make the right assumption about the likelihood of the value being
nil
.