Shall we always use [unowned self] inside closure in Swift
Asked Answered
M

12

510

In WWDC 2014 session 403 Intermediate Swift and transcript, there was the following slide

enter image description here

The speaker said in that case, if we don't use [unowned self] there, it will be a memory leak. Does it mean we should always use [unowned self] inside closure?

On line 64 of ViewController.swift of the Swift Weather app, I don't use [unowned self]. But I update the UI by using some @IBOutlets like self.temperature and self.loadingIndicator. It may be OK because all @IBOutlets I defined are weak. But for safety, should we always use [unowned self]?

class TempNotifier {
  var onChange: (Int) -> Void = {_ in }
  var currentTemp = 72
  init() {
    onChange = { [unowned self] temp in
      self.currentTemp = temp
    }
  }
}
Mexicali answered 20/6, 2014 at 5:11 Comment(6)
the image link is brokenColley
@DanielG.R. Thanks, I can see it. i.stack.imgur.com/Jd9Co.pngMexicali
Unless I'm mistaken, the example given in the slide is incorrect— onChange should be a [weak self] closure, since it's a public (internally, but still) property, so another object could get and store the closure, keeping the TempNotifier object around (indefinitely if the using object didn't let go of the onChange closure until it sees the TempNotifier is gone, via its own weak ref to the TempNotifier). If var onChange … were private var onChange … then [unowned self] would be correct. I'm not 100% certain of this though; somebody correct me please if I'm wrong.Pedigo
@Jake Lin ` var onChange: (Int) -> Void = {} ` do the curly braces represent an empty closure? same as it is in defining an empty array with [] ? I can't find the explanation in the Apple docs.Discommode
@Discommode yes, {} is the empty closure (the instance of the closure) as the default (doesn't do anything), (Int) -> Void is the closure definition.Mexicali
Who doesn't love a good analogy... weak someVarName is to someVarName? as unowned someVarName is to someVarName!.Biflagellate
F
928

No, there are definitely times where you would not want to use [unowned self]. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.

Example: Making an asynchronous network request

If you are making an asynchronous network request you do want the closure to retain self for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.

When to use unowned self or weak self

The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.

In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self] or [weak self]. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.

Specifically in the example from the video

In the example on the slide, TempNotifier owns the closure through the onChange member variable. If they did not declare self as unowned, the closure would also own self creating a strong reference cycle.

Difference between unowned and weak

The difference between unowned and weak is that weak is declared as an Optional while unowned is not. By declaring it weak you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned variable that happens to be nil, it will crash the whole program. So only use unowned when you are positive that variable will always be around while the closure is around

Frontwards answered 20/6, 2014 at 5:23 Comment(16)
To clarify, and related to this example, TempNotifier and the closure would both own self without the unowned or weak keywords?Hued
Hi. Great answer. I am struggling to understand unowned self. A reason to use weakSelf simply being 'self becomes an optional', is not enough for me. Why would I specifically want to use 'unowned self' #32936764Scrimshaw
@robdashnash, The advantage to using unowned self is that you don't have to unwrap an optional which can be unnecessary code if you know for sure by design, that it will never be nil. Ultimately, unowned self is used for brevity and perhaps also as a hint to future developers that you never expect a nil value.Frontwards
A case for using [weak self] in an asynchronous network request, is in a view controller where that request is used to populate the view. If the user backs out, we no longer need to populate the view, nor do we need a reference to the view controller.Chrissa
Great answer, thanks @Frontwards ! Does it mean that all closures that were created dynamically (i.e that are not retained as a strong argument) would never want to [unowned/weak self] ?Fuchsin
weak references are also set to nil when the object is deallocated. unowned references are not.Tachylyte
I am a bit confused. unowned is used for non-Optional while weak is used for Optional so our self is Optional or non-optional ?Runway
I tried the Entity Graph inspector in XCode without setting [unowned/weak self] and I couldn't find any trace of this ref cycle. Do anyone know if the default strong ref has changed since Swift 4 release? I guess, maybe it has becomed unowned by default as self is not optional inside a closure ?Gur
"So only use unowned when you are positive that variable will always be around while the closure is around" It makes it same as not using the keyword unowned, right?Donohue
@DakshGargas No, it does not make it the same. If you use unowned you say "Don't create a reference cycle – but self will always be alive when you access this closure". A hypothetical example would be: Instance A privately owns a closure C which captures A itself. So you need weak or unowned to avoid a retain cycle. However since C is private it cannot be called if A does not exist anymore, so self can never be nil.Colquitt
@K.Biermann then why not use weak self? To save oneself from the self != nil check?Donohue
@DakshGargas Yes, thats one reason – it's definitely syntactic sugar to avoid unnecessary (force) unwraps. But it is also a semantic hint because it makes clear that self must/will exist for the entire lifetime of the closure and if it does not it's a serious bug. I don't know if you're familiar with Rust, but it's quite similar to a lifetime statement (only that it sadly cannot be ensured during compile time yet).Colquitt
@K.Biermann Yeah... that's the explanation I used to give to the interviewees when they would fail to explain the difference since this is what I came up with, but never really found anyone providing a slid counter-argument or solid-agreement to this. Thanks for the clarification :)Donohue
@DakshGargas unowned is also faster than weak (it doesn't create side table for heap object)Diadem
@AndreyZhukov wow... I didn't know that part!! Thanks, man!Donohue
weak someVarName is to someVarName? as unowned someVarName is to someVarName!...In other words, if you use "unowned", you better be sure it isn't nil.Biflagellate
B
218

Update 11/2016

I wrote an article on this extending this answer (looking into SIL to understand what ARC does), check it out here.

Original answer

The previous answers don't really give straightforward rules on when to use one over the other and why, so let me add a few things.

The unowned or weak discussion boils down to a question of lifetime of the variable and the closure that references it.

swift weak vs unowned

Scenarios

You can have two possible scenarios:

  1. The closure have the same lifetime of the variable, so the closure will be reachable only until the variable is reachable. The variable and the closure have the same lifetime. In this case you should declare the reference as unowned. A common example is the [unowned self] used in many example of small closures that do something in the context of their parent and that not being referenced anywhere else do not outlive their parents.

  2. The closure lifetime is independent from the one of the variable, the closure could still be referenced when the variable is not reachable anymore. In this case you should declare the reference as weak and verify it's not nil before using it (don't force unwrap). A common example of this is the [weak delegate] you can see in some examples of closure referencing a completely unrelated (lifetime-wise) delegate object.

Actual Usage

So, which will/should you actually use most of the times?

Quoting Joe Groff from twitter:

Unowned is faster and allows for immutability and nonoptionality.

If you don't need weak, don't use it.

You'll find more about unowned* inner workings here.

* Usually also referred to as unowned(safe) to indicate that runtime checks (that lead to a crash for invalid references) are performed before accessing the unowned reference.

Bowman answered 24/11, 2015 at 10:48 Comment(9)
I'm tired of hearing the parrot explanation "use week if self could be nil, use unowned when it can never be nil". Ok we got it - heard it a million times! This answer actually digs deeper as to when self can be nil in plain english, which directly answers the OP's question. Thanks for this great explanation!!Ilanailangilang
Thanks @TruMan1, i'm actually writing a post on this that will end up on my blog soon, will update the answer with a link.Bowman
Nice answer, very practical. I'm inspired to switch some of my performance sensitive weak vars to unowned now.Thrum
"The closure lifetime is independent from the one of the variable" Do you have a typo here?Interlaken
Phrasing aside no, what i meant is that the weakly captured variable could not be available (it was released) when the closure is still reachable and someone invokes it.Bowman
If a closure always has the same lifetime as the parent object, wouldn't the reference count be taken care of anyway when the object is destroyed? Why can't you just use 'self' in this situation instead of bothering with unowned or weak?Desiderative
No one can take care of the situation you describe, ARC just adds retain/release calls as you would do manually. The parent/child relationship is an example of retain cycle, the parent self can't be released because the closure set its retain count at +1 and the closure cannot be released because its parent is for obvious reason retaining it. So, you end up with two objects strongly retaining each other, with a count that is at least at 1. The only way to handle this is to use some form of weak references, that in this case, allow the closure to have...Bowman
... some sort of reference to its parent without increasing its reference count.Bowman
LegendLength - When Umberto said the "closure has the same lifetime as the parent object" he meant related objects should have near-equal lifetimes by "your design". So domain knowledge of your application will decide if it's safe to use [unowned self]Northeast
S
153

I thought I would add some concrete examples specifically for a view controller. Many of the explanations, not just here on Stack Overflow, are really good, but I work better with real world examples (@drewag had a good start on this):

  • If you have a closure to handle a response from a network requests use weak, because they are long lived. The view controller could close before the request completes so self no longer points to a valid object when the closure is called.
  • If you have closure that handles an event on a button. This can be unowned because as soon as the view controller goes away, the button and any other items it may be referencing from self goes away at the same time. The closure block will also go away at the same time.

    class MyViewController: UIViewController {
          @IBOutlet weak var myButton: UIButton!
          let networkManager = NetworkManager()
          let buttonPressClosure: () -> Void // closure must be held in this class. 
    
          override func viewDidLoad() {
              // use unowned here
              buttonPressClosure = { [unowned self] in
                  self.changeDisplayViewMode() // won't happen after vc closes. 
              }
              // use weak here
              networkManager.fetch(query: query) { [weak self] (results, error) in
                  self?.updateUI() // could be called any time after vc closes
              }
          }
          @IBAction func buttonPress(self: Any) {
             buttonPressClosure()
          }
    
          // rest of class below.
     }
    
Suzannesuzerain answered 26/10, 2017 at 0:59 Comment(10)
This one needs more upvotes. Two solid examples showing how a button press closure won't exist outside the lifespan of the view controller, and therefore can use unowned, but most network calls that update UI need to be weak.Dich
So just to clarify, do we always use unowned or weak when calling self in a closure block? Or is there a time where we won't call weak/unowned? If so, could you provide an example for that too?Illimani
Thank you so much.Headwork
This gave me more deep understanding about [weak self] and [unowned self] Thanks a lot @possen!Contactor
This is great. what if I have an animation that is based on user interaction, but takes a while to finish. And then user moves to another viewController. I guess in that case I should still be using weak rather than unowned right?Interlaken
Can you explain why networkManager's closure could be called any time after the view controller closes, since networkManager is instantiated by the view controller? Would it not be released with the view controller?Immunity
The network request is an asynchronous request so it makes the request, and at some undetermined later time the response comes back. Other event loop events can happen and your view controller could be closed and freed. The button case this can't happen because the button will go away at the same time the vc goes away.Suzannesuzerain
For the animation question by @honey many animations are associated with the class of the view controller rather than the vc instance. This is not a retain cycle because it is on the class. I am thinking particular with view animations. Not sure I have clarified things but keep in mind that if the animation is attached to the class then you don't need to worry about the self retain cycle because self is not involved.Suzannesuzerain
What do you mean by attached to the class? Can you please add some related code to your answer?Interlaken
I mean a static member on a class rather than an instance member on a class. Static members don't have a self reference that can cause a circular reference. Like the following, UIView.animateWithDuration is a static member of UIView not on the instance in the following code: ``` UIView.animateWithDuration( 2.0, animations: { self.someView.alpha = 0.0 }, completion: { (finished) in return true } ```Suzannesuzerain
A
72

If self could be nil in the closure use [weak self].

If self will never be nil in the closure use [unowned self].

The Apple Swift documentation has a great section with images explaining the difference between using strong, weak, and unowned in closures:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

Abran answered 27/10, 2014 at 23:13 Comment(0)
J
55

Here is brilliant quotes from Apple Developer Forums described delicious details:

unowned vs unowned(safe) vs unowned(unsafe)

unowned(safe) is a non-owning reference that asserts on access that the object is still alive. It's sort of like a weak optional reference that's implicitly unwrapped with x! every time it's accessed. unowned(unsafe) is like __unsafe_unretained in ARC—it's a non-owning reference, but there's no runtime check that the object is still alive on access, so dangling references will reach into garbage memory. unowned is always a synonym for unowned(safe) currently, but the intent is that it will be optimized to unowned(unsafe) in -Ofast builds when runtime checks are disabled.

unowned vs weak

unowned actually uses a much simpler implementation than weak. Native Swift objects carry two reference counts, and unowned references bump the unowned reference count instead of the strong reference count. The object is deinitialized when its strong reference count reaches zero, but it isn't actually deallocated until the unowned reference count also hits zero. This causes the memory to be held onto slightly longer when there are unowned references, but that isn't usually a problem when unowned is used because the related objects should have near-equal lifetimes anyway, and it's much simpler and lower-overhead than the side-table based implementation used for zeroing weak references.

Update: In modern Swift weak internally uses the same mechanism as unowned does. So this comparison is incorrect because it compares Objective-C weak with Swift unonwed.

Reasons

What is the purpose of keeping the memory alive after owning references reach 0? What happens if code attempts to do something with the object using an unowned reference after it is deinitialized?

The memory is kept alive so that its retain counts are still available. This way, when someone attempts to retain a strong reference to the unowned object, the runtime can check that the strong reference count is greater than zero in order to ensure that it is safe to retain the object.

What happens to owning or unowned references held by the object? Is their lifetime decoupled from the object when it is deinitialized or is their memory also retained until the object is deallocated after the last unowned reference is released?

All resources owned by the object are released as soon as the object's last strong reference is released, and its deinit is run. Unowned references only keep the memory alive—aside from the header with the reference counts, its contents is junk.

Excited, huh?

Jammiejammin answered 31/12, 2015 at 6:53 Comment(0)
W
43

There are some great answers here. But recent changes to how Swift implements weak references should change everyone's weak self vs. unowned self usage decisions. Previously, if you needed the best performance using unowned self was superior to weak self, as long as you could be certain that self would never be nil, because accessing unowned self is much faster than accessing weak self.

But Mike Ash has documented how Swift has updated the implementation of weak vars to use side-tables and how this substantially improves weak self performance.

https://mikeash.com/pyblog/friday-qa-2017-09-22-swift-4-weak-references.html

Now that there isn't a significant performance penalty to weak self, I believe we should default to using it going forward. The benefit of weak self is that it's an optional, which makes it far easier to write more correct code, it's basically the reason Swift is such a great language. You may think you know which situations are safe for the use of unowned self, but my experience reviewing lots of other developers code is, most don't. I've fixed lots of crashes where unowned self was deallocated, usually in situations where a background thread completes after a controller is deallocated.

Bugs and crashes are the most time-consuming, painful and expensive parts of programming. Do your best to write correct code and avoid them. I recommend making it a rule to never force unwrap optionals and never use unowned self instead of weak self. You won't lose anything missing the times force unwrapping and unowned self actually are safe. But you'll gain a lot from eliminating hard to find and debug crashes and bugs.

Warfourd answered 26/12, 2017 at 22:31 Comment(6)
Thank you for the update and Amen on the last paragraph.Postdiluvian
So after the new changes Is there ever a time where weak can't be used in place of an unowned?Interlaken
I would like to know the answer to the question right above by @mfaani.Glassy
Am I correct then that the worst thing that can happen when we use [unowned self] is the app can crash, and the worst thing to happen when using [weak self] is expense on iOS resources? What happens when I use ``` guard let self = self else { return }```? Could the self constant afterwards be set to nil, thus causing a crash, or does that self keep the object it refers and all other objects referring to it in memory until the code is finished and all memory is released, or does self release the memory it refers to as well all references that directly or indirectly depend on what self refers?Glassy
unowned can cause a crash, and weak won't but is less efficient. Using your guard statement is fine to use with weak self, it's not increasing the reference count, but its also not executing the code following the guard unless self is still allocated. Self should stay allocated while you use it since you are on the same thread.Warfourd
I agree, the advantage of using unowned is currently so minimal compared to potential crashes that it can cause that there is no real reason to use it at all. Maybe if you have like a million of objects at the same time then you might see a difference in performance but that is almost never a real case.Lingerie
H
5

According to Apple-doc

  • Weak references are always of an optional type, and automatically become nil when the instance they reference is deallocated.

  • If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference

Example -

    // if my response can nil use  [weak self]
      resource.request().onComplete { [weak self] response in
      guard let strongSelf = self else {
        return
      }
      let model = strongSelf.updateModel(response)
      strongSelf.updateUI(model)
     }

    // Only use [unowned self] unowned if guarantees that response never nil  
      resource.request().onComplete { [unowned self] response in
      let model = self.updateModel(response)
      self.updateUI(model)
     }
Hypothetical answered 9/8, 2017 at 10:52 Comment(0)
R
1

unowned is similar to weak they don't a retained object from being destroyed, but weak variables turned to nil when the object its a reference to no longer exists, which we can handle with the normal checking of nils, unowned will just become garbage, you can't tell they are no longer garbage and using them will crash. The problem with weak is if an object has references to it by weak variables, when its destroyed, it has to go through every reference to it and set that variable to nil, this clearly is going to be expensive, using unowned instead is going just crash and finding this kind of bug is going to be difficult. One place to use unowned is if you are creating some carefully contained datatype, which has a clear interface, and its internals are not directly accessible, for you implementation it may be useful to have lots of circular references but that are self contained, you can used unowned references to let you break those circular references, with out the expense of weak variables, for example you may have a node tree, and each node needs has to have a reference to its parent, deleting a node is going to delete all its children, so there is no point of all the children having to have all there parent references set to nil.

Rusticate answered 9/2, 2022 at 7:40 Comment(4)
Am I correct then that the worst thing that can happen when we use [unowned self] is the app can crash, and the worst thing to happen when using [weak self] is expense on iOS resources? What happens when I useGlassy
Even if you know your closure is going to be executed straight away, and its not going to be stored and executed later on, if you use unowned, its possible your object could be released mid execution of your closure because of what another thread does. The only place I would use unowned is if you have built your own data structure, which is a black box to users, and you can get performance benefits from using unowned, and you know because of the way your logic works, that an unowned reference can not be accessed when its no longer valid.Rusticate
How cold another thread cause my object to be released if I have a reference to the object, even if my reference to the object is using [unowned self]? I have a reference to the object. Doesn't ARC ensure that the object would not be released if I have a reference to it, even if it's an [unowned self] reference? I thought ARC only releases the object for cleanup if there are no references to it.Glassy
ARC simply guarantees that's reference counts are atomic. So you have a closure that runs in one thread, for an object that's contained in an array, and the object is removed from the array by another thread, where is the strong reference to your object now, your have specified using [unowned self] to say don't use a strong reference to self in you closure, so there are no strong references to the object you closure can still be operating on, in fact your closure itself could have a strong reference on it, not even requiring threads for this to occur.Rusticate
D
0

If none of the above makes sense:

tl;dr

Just like an implicitly unwrapped optional, If you can guarantee that the reference will not be nil at its point of use, use unowned. If not, then you should be using weak.

Explanation:

I retrieved the following below at: weak unowned link. From what I gathered, unowned self can't be nil but weak self can be, and unowned self can lead to dangling pointers...something infamous in Objective-C. Hope it helps

"UNOWNED Weak and unowned references behave similarly but are NOT the same."

Unowned references, like weak references, do not increase the retain count of the object being referred. However, in Swift, an unowned reference has the added benefit of not being an Optional. This makes them easier to manage rather than resorting to using optional binding. This is not unlike Implicitly Unwrapped Optionals . In addition, unowned references are non-zeroing. This means that when the object is deallocated, it does not zero out the pointer. This means that use of unowned references can, in some cases, lead to dangling pointers. For you nerds out there that remember the Objective-C days like I do, unowned references map to unsafe_unretained references.

This is where it gets a little confusing.

Weak and unowned references both do not increase retain counts.

They can both be used to break retain cycles. So when do we use them?!

According to Apple's docs:

“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialisation.”

Donohue answered 28/6, 2019 at 5:49 Comment(0)
M
0
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "AnotherViewController")
        self.navigationController?.pushViewController(controller, animated: true)

    }

}



import UIKit
class AnotherViewController: UIViewController {

    var name : String!

    deinit {
        print("Deint AnotherViewController")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        print(CFGetRetainCount(self))

        /*
            When you test please comment out or vice versa

         */

//        // Should not use unowned here. Because unowned is used where not deallocated. or gurranted object alive. If you immediate click back button app will crash here. Though there will no retain cycles
//        clouser(string: "") { [unowned self] (boolValue)  in
//            self.name = "some"
//        }
//


//
//        // There will be a retain cycle. because viewcontroller has a strong refference to this clouser and as well as clouser (self.name) has a strong refferennce to the viewcontroller. Deint AnotherViewController will not print
//        clouser(string: "") { (boolValue)  in
//            self.name = "some"
//        }
//
//


//        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser (self.name) has a weak refferennce to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)
//
//        clouser(string: "") { [weak self] (boolValue)  in
//            self?.name = "some"
//        }


        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser nos refference to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)

        clouser(string: "") {  (boolValue)  in
            print("some")
            print(CFGetRetainCount(self))

        }

    }


    func clouser(string: String, completion: @escaping (Bool) -> ()) {
        // some heavy task
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            completion(true)
        }

    }

}

If you do not sure about [unowned self] then use [weak self]

Myungmyxedema answered 16/12, 2019 at 7:38 Comment(0)
H
0

You have references that you don’t want to be strong references, in order to avoid circular references. So at some point when the last strong reference to an object gets removed, the object itself gets removed.

What happens to other non-strong references? Obviously they don’t refer to that object anymore, which is problematic. There are two kinds of ways to handle this:

  1. Weak reference. When the last strong reference to an object goes away, all weak references are set to nil, so a developer can check if the referenced object is there anymore. Quite obviously a weak reference must be an optional, otherwise it couldn’t be set to nil. The strategy to use a weak reference: You write “if let ref = weakref”. Either the reference was still there, and since you just assigned it to a strong reference, it will remain until the end of the “if let”. If you don’t do it this way then you may access the same weak reference twice, and it may be (unexpectedly) not nil on the first access, but nil on the second.

  2. You create an unowned reference. If the object goes away, nobody will tell you. It will look as if you have a reference when to the referred object has gone away. You must only use this if you are 100% sure that the referenced object cannot go away early.

Use unowned if you have measured that it is faster, and when you are 100% that you don’t use the rubbish when the object is gone.

Halfdan answered 11/11, 2022 at 11:29 Comment(0)
I
0

You can use unowned or weak self to get rid of retain cycles.

The big difference is that you use [weak self] when the instance being referenced has a shorter life time than the instance or property referring to it, and use [unowned self] when the instance being referenced has the same or greater life time than the instance/property referring to it.

For example in this code

class TempNotifier {
    var onChange: (Int) -> Void = {_ in }
    var currentTemp = 72
    init() {
        onChange = { [unowned self] temp in
        self.currentTemp = temp
        }
    }
}

It can be assured that the onChange closure will not outlive the class instance it is declared. You can be consent on not calling this onChange method after the instance of TempNotifier is deallocated.

On the other hand in network call methods, especially if you use @escaping closures then its highly recommended that you should not use [unowned self] because these closures outlive the class instance and can be called even when the class instance is deallocated. It's better to use [weak self] in these cases.

Ijssel answered 3/3 at 2:57 Comment(2)
What info are you providing that can't already be found in many of the existing answers?Penurious
It's the way of explaining, and not necessarily need to be conceptually different from whatever answer given before.Ijssel

© 2022 - 2024 — McMap. All rights reserved.