3

Xcode produces outlets as weak vars with implicit unwrapping, like this:

@IBOutlet weak var nameTextField: UITextField!

I wonder why it didn't just make onowned var, which - in my understanding - behaves exactly the same, but keeps the type non-optional. Is there any difference between these two?

weak var foo: UITextField!
unowned var foo: UITextField
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Robo Robok
  • 21,132
  • 17
  • 68
  • 126
  • 1
    2-phase initialization. The outlets are assigned after the initialization, therefore they must be optional. It usually does not matter whether they are kept `weak` or `strong` but `unowned` is not correct. – Sulthan Jul 23 '17 at 11:14
  • @Sulthan I always wondered why an IBOutlet gets hit on the breakpoint twice. So I created a project, dragged a label into the viewController and set a breakpoint on it. First breakpoint happens before `viewDidLoad` or `init`. If I print the label it shows it's `nil`. 2nd time I hit the breakpoint is after `init` but still before `viewDidLoad`. This time if I print it, it shows: `Optional` – mfaani Jul 23 '17 at 12:04

5 Answers5

6

A weak variable has a default value, namely nil, so your code is legal because the outlet property has a value at object creation time (before the outlet is actually connected).

But an unowned variable would have no default value and your code wouldn't compile. Try it.

Also the entire concept would be wrong. unowned is for a thing with a guaranteed independent existence and which you can't live without. A subview of a view controller's view satisfies neither of those.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I don't think this is the reason. The reason for outlet being declared as weak is the container view of the outlet would always have strong reference over it. Its can not be unowned because unowned is not available for Objc runtime. weak does not have default value nil. Outlet is implicitly unwrapped. So it should always have non nil value while accessing. – Mohammad Sadiq Jul 22 '17 at 20:11
  • "because unowned is not available for Objc runtime" @MohammadSadiq It is non-ARC `weak` in Objective-C. – matt Jul 22 '17 at 22:56
0

Yes, there is difference. Other than the default value issue, there is a way to check whether or not the weak value currently exists:

if let nameTextField = nameTextField {
    // do smth
}

on the other hand, I don't think there is a way to check if the unowned is there and valid to access. Whenever an unowned is used, it's supposed to always be there, which is not true in the case of IBOutlet. The outlets are not set until the view controller is loaded from the storyboard.

Hope this helps!

timaktimak
  • 1,380
  • 1
  • 12
  • 21
0

Unowned types are dangerous and best avoided. An unowned variable is equivalent to the Objective C unsafe_unretained type.

If the object that's pointed to by an unowned reference gets released, the unowned reference won't be set to nil. If you then try to reference the object later, your code can't tell if it's still valid or not. If you try to call a method or read/write an instance variable, you may crash if the object has been released.

(Then there's the fact that the variable doesn't have a default value, as matt says in his answer.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Implicitly unwrapped optionals would also cause it to crash. My understanding is Outlets are good candidates for unowned, but because unowned is not available to Obc runtime , it is declared as weak , implicitly unwrapped. – Mohammad Sadiq Jul 22 '17 at 20:21
  • It's true that implicitly unwrapped optionals crash if nil, but the crash is guaranteed, immediate and obvious. An unowned reference to an object that has been released leads to undefined behavior, and can cause memory corruption that might not show up until some later time. Those sorts of bugs are nasty and hard to find. – Duncan C Jul 22 '17 at 20:25
  • No, outlets are not good candidates for unowned. You should avoid unowned references and use weak instead wherever possible. – Duncan C Jul 22 '17 at 20:26
  • OK. But is it really the reason for outlet being weak and implicitly unwrapped? Because implicitly unwrapped itself implies that its not supposed to go nil while accessing. – Mohammad Sadiq Jul 22 '17 at 20:27
  • 1
    Actually an `unowned` reference will always raise a runtime error upon attempting to access a deallocated object (so in that regard is equivalent to force unwrapping a `weak` reference). `unowned(unsafe)` is what will give you undefined behaviour. The way the runtime knows to raise a runtime error is actually because Swift keeps a separate reference count for unowned references. When the strong ref count is zero, `deinit` gets called, then a runtime error will be raised from an `unowned` access. Then when the `unowned` ref count hits zero, only then will the object *actually* be deallocated. – Hamish Jul 22 '17 at 20:32
  • Although, like with many other safety checks (such as the runtime error with force unwraps), the runtime error raised by an illegal unowned access will be removed in `-Ounchecked` builds, at which point you will get undefined behaviour. But generally you should avoid `-Ounchecked` builds. See https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID381 & the comments in the header https://github.com/apple/swift/blob/master/stdlib/public/SwiftShims/RefCount.h#L54 for more info. – Hamish Jul 22 '17 at 21:04
0

unowned var foo: UITextField should be initialized during view controller initialization, but it's impossible because outlet can be initialized only after view is created, and view is created only when view controller is shown (more precisely when view property is accessed).

mfaani
  • 33,269
  • 19
  • 164
  • 293
Alexey Kozhevnikov
  • 4,249
  • 1
  • 21
  • 29
  • Yes, I think that's the reason why it uses `weak` instead. `unowned` behaves just like any other property in terms of initialization. So they would need to do optional `unowned`, which doesn't make much sense when we have `weak` :) – Robo Robok Jul 23 '17 at 11:31
0

It used to be that optionals could not be unowned. That's possible now, so unowned is appropriate. This is probably not done automatically because it would confuse somebody.

@IBOutlet private unowned var uiObject: UIObject!