3

I´m trying to integrate Face/Touch ID Login and I saw [unowned self] in Apple's documentation, inside a closure. What is that and what are the benefits?

Example code:

let context = LAContext()
    var error: NSError?
    
    if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
        let reason = "Identify yourself!"
        
        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
            [unowned self] (success, authenticationError) in
            
            DispatchQueue.main.async {
                if success {
                    print("Authenticated!")
                } else {
                    // error
                }
            }
        }
    } else {
        // no biometry
    }
shim
  • 9,289
  • 12
  • 69
  • 108
SwiftiSwift
  • 7,528
  • 9
  • 56
  • 96
  • 2
    [Might help](https://stackoverflow.com/questions/24320347/shall-we-always-use-unowned-self-inside-closure-in-swift); ["WEAK, STRONG, UNOWNED, OH MY!"](https://krakendev.io/blog/weak-and-unowned-references-in-swift); [Swift Retention Cycle in Closures and Delegate](https://blog.bobthedeveloper.io/swift-retention-cycle-in-closures-and-delegate-836c469ef128); [Automatic Reference Counting](https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html); [How To Prevent Memory Leaks In Swift Closures](https://stablekernel.com/how-to-prevent-memory-leaks-in-swift-closures/) – MadProgrammer Jan 21 '19 at 23:15
  • 1
    [Unowned vs Weak](https://medium.com/@fahad_29644/unowned-vs-weak-614ac71ac516); [Functional programming: Closure reference cycle and fix](https://medium.com/@abhimuralidharan/functional-programming-closure-reference-cycle-and-fix-f42cc53c6213) – MadProgrammer Jan 21 '19 at 23:16
  • will look into it later. Thanks! – SwiftiSwift Jan 21 '19 at 23:18
  • Possible duplicate of [Shall we always use \[unowned self\] inside closure in Swift](https://stackoverflow.com/questions/24320347/shall-we-always-use-unowned-self-inside-closure-in-swift) – Cristik Jan 22 '19 at 06:05

2 Answers2

1

Long story short, it's the same as weak!, since unowned references are just weak references that are guaranteed to have a value.

unowned is used when you're sure that the reference will NEVER be nil, and therefore, it can only be evaluated with non nil values.

Like weak references, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is assumed to always have a value. Because of this, an unowned reference is always defined as a non-optional type. (Apple Docs)

Check this other answer: What is the difference between a weak reference and an unowned reference?

Docs: ARC Documentation

Gustavo Vollbrecht
  • 3,188
  • 2
  • 19
  • 37
1

The unowned qualifier, like weak, prevents the closure from establishing a strong reference to to self which can be helpful in preventing strong reference cycles. The benefit of unowned over weak is that it’s a tad more efficient in optimized builds, not requiring it to keep track of this reference and go back and set it to nil when the object to which it references is deallocated. The unowned reference also is not an optional, meaning that you don’t have to unwrap it, eliminating syntactic noise and simplifying one’s code.

But you obviously can’t use unowned in any situation where the object might be deallocated, because it obviously can no longer keep a reference to the memory for a deallocated object.

Interestingly, the evaluatePolicy(_:localizedReason:reply:) documentation says, “This method asynchronously evaluates an authentication policy.” Any time you’re dealing with an asynchronous method, it is not advisable to use unowned, because you cannot be assured that the object in question hasn’t been deallocated in the intervening time. Only use unowned in those specific situations where you know, for a fact, that the closure cannot be called if the object has been deallocated. That would not appear to be the case here.

Bottom line, use unowned to avoid strong reference cycles and where you want cleaner, slightly more efficient code. But only do so when you know that it is impossible for the object to be deallocated before closure is called.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • what do you mean with deallocated? – SwiftiSwift Jan 24 '19 at 21:15
  • When the last strong reference is removed, the object will be deallocated and the memory it used to occupy will be made available for other purposes. In the case of a view controller, it generally is deallocated once it’s dismissed. So if you have a view controller that is dismissed before the asynchronous closure is called, the `unowned` reference will be a dangling pointer, still point to the memory it used to occupy, whereas a `weak` reference will be set to `nil` as soon as the view controller is deallocated, avoiding any unsafe references to the old memory address. – Rob Jan 24 '19 at 21:34
  • so with unowned i have always access to self even if the viewcontroller is deallocated right? – SwiftiSwift Jan 26 '19 at 09:19
  • That depends upon what you mean by “access to”. If the view controller has been deallocated, you obviously don’t have “access to” it, because it’s gone. What you’ve got is a reference to that location of memory that assumes the view controller is still there, even though it’s not. In short, if it’s at all possible for `self` to be deallocated before the closure runs, you simply shouldn’t use `unowned`. But if you’ve got a different scenario where it’s technically impossible for it to be deallocated before the closure runs, then use `unowned` and enjoy the modest benefits. – Rob Jan 26 '19 at 09:46
  • "but only when you know that it is impossible for the object to be deallocated before closure is called." like when? Do you have an answer that actually requires `unowned` to be used? I can't find one that's simple to understand :/ – mfaani May 15 '19 at 22:13
  • See [The Swift Programming Language: ARC: Resolving Strong Reference Cycles for Closures](https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html#ID57) for examples. Common scenario is (a) the closure is called synchronously; and (b) the closure is called by something further down the object ownership graph. A practical example: a `UIButton` subclass has closure property that is called when the button is tapped. View controller can safely use `[unowned self]` in capture list because if the view controller is dismissed, the button is gone, too. – Rob May 15 '19 at 23:46