Replace the reference types weak and unowned with nonstrong

Personally, I think you should still handle the result, even if the view that presented that information is no longer on screen. Most Apps which fetch data from a server have some kind of local cache, and updating that cache is still useful. You already did the hard (and battery-draining) part - why throw that away?

Besides fetching data, other requests may perform some kind of remote action (like purchasing something), and handling those responses is always important, even if it’s an error. Ideally you would predict all such cases and make it impossible to leave the view until the transaction is complete, but it can still be useful to have some kind of fallback handler in case you make a mistake and forget to make something modal. Otherwise the user might try to buy the product again, which is worse; it’s more hassle for the customer and requires a support rep to investigate and issue a refund.

I should add: this is why decoupling your presentation (view/view-controllers) from your data (model/model-controllers) is so useful.

1 Like

@Lantua. To clarify the proposal, it's not trying to fix the wrong-choice bug, it's trying to eliminate the wrong-choice bug. The proposal eliminates the need for the coder to make the choice (weak or unowned) in the first place. That elimination is done by having the compiler make that choice.

I'll modify the proposal to make that clear.

Of course there are a few types of remaining questions:

  1. Can the compiler can even be modified to make that choice?
  2. If it can, do we want to (or is the current way acceptable)?

You cannot do this. (See above under "No.")

There is no general mechanism for the compiler to reason about the lifetimes of objects. You actually have to do it yourself, case by case.

In addition, weak referencing can be horribly inefficient when large numbers of objects are created and destroyed. The compiler should never use weak automatically. You actually have to choose it yourself, case by case.

Yes to both.

2 Likes

This is a nice improvement, but I suspect less readability where weak and unowned provide better explicit meaning. As per proposal, we don't need to use two keywords to define ownership which have the same meaning - they don't hold a strong reference, but only differ in unwrapping where unowned references are automatically unwrapped.

Automatically unwrapped unowned references doesn't mean they always have a value, but they're expcted to have one. The developer need to choose correctly which one to use depending on the scenario. The same expectations remain in this proposal as well with only differing syntax.

To represent a weak reference, one can use nonstrong optional types, while for unowned types nonstrong non-optional types.

The syntax also provides same semantics as weak and unowned references do as of now. Because of the nonstrong keyword and the optional/nonoptional marker.

A slightly different suggestion:

  • nonstrong must be optional (just like weak)
  • the developer can choose to force-unwrap the optional (just like any optional)

For example:

let nonstrong customer1: Customer?  // like `weak`
let nonstrong customer2: Customer!  // like `unowned`

In a capture list, where you don't typically name the type, you might express that like this:

[nonstrong self!] ...

with a ! after the variable name.

To me this proposal highlights the lack of good documentation about what difference between these two constructs actually do under the hood.

I haven’t looked at the docs recently but when I last did so I was strongly convinced that they were written by someone who took for granted that “unowned” is obvious and “weak” is a new magic addition. This implies knowledge of the Objective C history of Swift (and importantly, ARC).

I only understood the difference once I learned that unowned is at its core a very “old” concept that essentially disables reference counting (especially retaining) altogether, whereas weak is a newer and highly magical construct that has an equally impressive performance cost.

As soon as I realised that, I realised that both concepts have a very clear place in the Swift ecosystem, making the proposal here a nonstarter for me.

The point of unowned is not about something being nonoptional at all. It’s specifying a guarantee on the programmer’s behalf that the unowned object will be alive as long as the object it’s attached to. You’re begging for the inevitable crash if you as a programmer break that guarantee.

weak on the other hand is only optional because you’re specifying that you expect the referenced object to maybe have disappeared by the time you go to use it (and are ok with that in the sense that your program is forced to deal with the possibility it has disappeared). It is a convenient way of allowing for this possibility without having to jump through hoops of nullifying strong references yourself in cases where you might need them later (e.g. in a callback).

The two keywords represent totally different use cases and, as others have pointed out, there’s no way for a compiler to know your intent here. What I would agree on is making all of this clearer to new users (especially those who don’t have an intimate knowledge of the history or inner-workings of ARC)

8 Likes