3

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?

Boon
  • 40,656
  • 60
  • 209
  • 315
  • Apple started annotating the objc frameworks so that you get either a non-optional or an optional, they are reducing the number of implicitly unwrapped optionals. – Kametrixom Jun 17 '15 at 01:50
  • @Kametrixom Thanks, I know that - I am asking what could happen in pre-nullability era. – Boon Jun 17 '15 at 01:52

2 Answers2

6

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 return nil. 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 be nil 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 actually non-nil. Most of the reason for this is probably because you figure most of these methods actually never return nil.

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:

override func someFunc(implicitVal: String!) -> String {
    return implicitVal ?? "It was nil!"
}

override func someOtherFunc(implicitVal: String!) -> String {
    return implicitVal
}

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.

nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • Thanks. I am still not totally getting it. If the framework method can return nil, why use implicitly unwrapped optional (which will cause a crash) instead of optional? – Boon Jun 17 '15 at 12:24
  • Because an Objective-C file which hasn't been updated with the nullability annotations only returns the implicitly unwrapped optional. That's how the languages are defined to work. – nhgrif Jun 17 '15 at 12:25
  • If the compiler can't determine the Objective-C method is returning a nullable or not, why not define everything as optional (because the inherent nature of pointer is such that it can be nil)? Rather than implicitly unwrapping an optional - which already implies the return value is an optional (and can therefore be unwrapped) – Boon Jun 17 '15 at 12:33
  • I expanded my answer. If what I have doesn't suffice, then we're back to the point that your questions always seem to go to in that it needs to be asked of one of the language designers... – nhgrif Jun 17 '15 at 12:34
  • Maybe - and some folks here may have insights on that, even though they are not the original implementers. Don't think we should assume that only the original team can answer language design question or that such question is not valuable on SO. – Boon Jun 17 '15 at 12:36
  • @Boon Do you understand now, after reading my answer? Are you aware of how the nullability annotations work from the Objective-C end? The compiler makes no assumptions. Non-optional or optional means the Objective-C author has annotated the code. Implicitly unwrapped means the Objective-C author has not annotated the code. As of Xcode 7, all of the Apple frameworks will be annotated and there will be no implicitly unwrapped optionals in Apple's frameworks. – nhgrif Jun 17 '15 at 12:38
  • Still going through your answers and testing things out. I take it seriously - thanks for the updated answer. – Boon Jun 17 '15 at 12:39
  • @Boon It might also be helpful [to read this answer](http://stackoverflow.com/a/29401454/2792531) which actually describes what you have to do in order to annotate your Objective-C code so that an Objective-C library you wrote won't show up as using implicitly unwrapped optionals in Swift. – nhgrif Jun 17 '15 at 12:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/80779/discussion-between-boon-and-nhgrif). – Boon Jun 17 '15 at 12:49
1

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)?

No. An implicitly-unwrapped optional is an optional -- which means nil is a perfectly acceptable value for it. Having an implicitly-unwrapped optional as nil doesn't crash, only if you try to access a member on it directly without optional-binding or optional-chaining does it crash.

Or does Apple make sure only those Objective-C methods that absolutely do not return nil get declared as implicitly unwrapped optional?

If it were known to not return nil, then Apple, after auditing, would declare it as non-optional, not an implicitly-unwrapped optional. Only if it is not known whether it may return nil or not, does it return implicitly-unwrapped optional.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • Perhaps more accurately, only if the developer has taken the time to add annotations will it return something other than implicitly-unwrapped optionals. – nhgrif Jun 18 '15 at 12:37