Swift.org Blog: Reimplementation of Implicitly Unwrapped Optionals

There is a new blog article on Swift.org titled Reimplementation of Implicitly Unwrapped Optionals. It discusses the completion of SE-0054 and the valuable implications for Swift users.

Thank you so much to @rudkx for authoring this post!

Please feel free to use this forum thread to provide comments or ask questions about the material in the blog article.

8 Likes

Possible typo, the greater-than sign after “as” should probably be a colon or em-dash:

Fixed. Update to post coming shortly.

Another one, code block not rendering properly, triple-backticks showing as text:

Edit: actually there several instances of this.

Indeed. Differences between Markdown renderers. I've tweaked the source to use ~~~ instead. Should update shortly.

You might occasionally find it convenient to use implicit unwrapping when declaring @IBOutlet properties, or in other places where you know you won’t access a value until it has been fully initialized. However, you are usually better off avoiding implicit unwrapping and should use explicit unwrapping through if let and guard let. When you’re certain it’s safe, use explicit force-unwrapping via !.

The @IBOutlet part confused me a bit.

Are you saying this pattern should not be used?
@IBOutlet weak var tableView: UITableView!

Sorry if that paragraph wasn't entirely clear.

@IBOutlet is just used as an example of where you might find it convenient to use an implicitly unwrapped optional. What I was trying to get across is that although there may be some specific cases where you may want to use implicit unwrapping as a tool, it shouldn't be the tool of choice in most circumstances.

For example I cannot think of a case where I would recommend writing a Swift method that has implicitly unwrapped optionals in its parameter list, despite that being one of the places where they are still allowed. You will of course sometimes see Objective-C methods that get imported with parameter lists that include implicitly unwrapped optionals because that is what we default to for nullable types in methods that have not been audited for nullability.

What I would generally discourage is the use of implicitly unwrapped optionals as a general strategy to circumvent the rules around initializing class properties. I'm not sure how common that practice is, but I have seen projects where every property of every class is declared as implicitly unwrapped for this reason.

3 Likes

Note that the result of AnyObject lookup is treated as an optional that is implicitly unwrapped. If you lookup a property that itself is also declared as implicitly unwrapped, the expression now has two levels of implicit unwrapping.

What is meant by "AnyObject lookup"? The blog post contains the following example code:

func getLabel(object: AnyObject) -> UILabel {
  return object.property // forces both optionals, resulting in a UILabel
}

But that doesn't work, right? As far as I know, AnyObject doesn't have a property with the name "property" and it can't be extended either.

Thanks and totally understand now.

FWIW, in the last year, I've seen developers coming from other experience making all class properties:
var name: String!

My conclusions why are:

  1. They don't understand initializer chaining
  2. They feel like it's to much boilerplate for initializer chaining
    1. Would love an auto-synthesized init for all properties as an overridable convenience
  3. They don't want to use guard let or if let
    1. Not saying I think this makes sense not to learn the patterns
  4. Initializer chaining not available

On the last point, @IBOutlet weak var tableView: UITableView! being a correct pattern in ViewControllers leads the less experienced to believe that's the right thing always. Then that mis-learning gets propagated to code that definitely doesn't need it.

Just my $0.02

1 Like

See "Dynamic Method Lookup" in the Swift-ObjC Interoperability documentation.

In short, AnyObject works somewhat like id in ObjC; you can send it any method known to be defined on any ObjC class. It's a concession to ObjC interoperability, one that is rarely actually needed.

1 Like

Thank you! I should finally read that document!

Minor nit: In the 5th paragraph of the post, you abbreviate Implicitly Unwrapped Optionals as IOUs when it probably should be IUOs.

Does this fix the case where implicitly unwrapped optionals and optionals don't play nice in a protocol?

eg:

protocol TextEntryView {
    var text: String?
}

// This works.
class UITextField: TextEntryView {} 


// This doesn't work because it's declaration has `text: String!`
class UITextView: TextEntryView {} 

This is a slight problem which I found frustrating from a dev perspective. In my mind implicitly unwrapped optionals should have the same conformance behaviour as optionals when it comes to protocol adherence.

Fixed. Thank you!

1 Like

The behavior here remains the same as it was previously. Relaxing restrictions like these were not part of SE-0054, and thus not considered.

This may be a good issue to raise in the Evolution category.

1 Like