Shall we always use [unowned self] inside closure in Swift
Solution 1
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
Solution 2
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.
Scenarios
You can have two possible scenarios:
-
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. -
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.
Solution 3
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 soself
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 fromself
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. }
Solution 4
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:
Solution 5
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 withx!
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 forunowned(safe)
currently, but the intent is that it will be optimized tounowned(unsafe)
in-Ofast
builds when runtime checks are disabled.
unowned
vs weak
unowned
actually uses a much simpler implementation thanweak
. Native Swift objects carry two reference counts, andunowned
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 whenunowned
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?
Jake Lin
Dad of 👶 & 👦, iOS dev. Passionate about design and animation. Make @IBAnimatable and SwiftWeather. https://github.com/JakeLin
Updated on August 25, 2022Comments
-
Jake Lin almost 2 years
In WWDC 2014 session 403 Intermediate Swift and transcript, there was the following slide
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@IBOutlet
s likeself.temperature
andself.loadingIndicator
. It may be OK because all@IBOutlet
s I defined areweak
. 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 } } }
-
Con Antonakos over 9 yearsTo clarify, and related to this example,
TempNotifier
and the closure would both ownself
without theunowned
orweak
keywords? -
Admin over 8 yearsHi. 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' stackoverflow.com/questions/32936264/…
-
drewag over 8 years@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.
-
David James about 8 yearsA 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. -
TruMan1 about 8 yearsI'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!!
-
uraimo about 8 yearsThanks @TruMan1, i'm actually writing a post on this that will end up on my blog soon, will update the answer with a link.
-
original_username almost 8 yearsNice answer, very practical. I'm inspired to switch some of my performance sensitive weak vars to unowned now.
-
mfaani almost 8 years"The closure lifetime is independent from the one of the variable" Do you have a typo here?
-
uraimo almost 8 yearsPhrasing 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.
-
LegendLength about 7 yearsIf 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?
-
uraimo about 7 yearsNo 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...
-
uraimo about 7 years... some sort of reference to its parent without increasing its reference count.
-
shinyuX about 7 yearsGreat answer, thanks @drewag ! 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] ?
-
BergQuester over 6 years
weak
references are also set tonil
when the object is deallocated.unowned
references are not. -
Tim Fuqua over 6 yearsThis 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.
-
luke over 6 yearsSo 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?
-
Muhammad Nayab over 6 yearsI am a bit confused.
unowned
is used fornon-Optional
whileweak
is used forOptional
so ourself
isOptional
ornon-optional
? -
motto over 6 yearsThank you for the update and Amen on the last paragraph.
-
Shawn Baek about 6 yearsThank you so much.
-
Tommy almost 6 yearsThis gave me more deep understanding about [weak self] and [unowned self] Thanks a lot @possen!
-
Olympiloutre almost 6 yearsI 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 defaultstrong
ref has changed since Swift 4 release? I guess, maybe it has becomedunowned
by default asself
is not optional inside a closure ? -
mfaani over 5 yearsThis 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 thanunowned
right? -
mfaani over 5 yearsSo after the new changes Is there ever a time where
weak
can't be used in place of anunowned
? -
Mike Taverne over 5 yearsCan you explain why
networkManager
's closure could be called any time after the view controller closes, sincenetworkManager
is instantiated by the view controller? Would it not be released with the view controller? -
possen over 5 yearsThe 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.
-
possen over 5 yearsFor 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 becauseself
is not involved. -
mfaani over 5 yearsWhat do you mean by attached to the class? Can you please add some related code to your answer?
-
possen over 5 yearsI 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 } ```
-
Daksh Gargas about 5 years"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? -
Karthik Murugesan almost 5 yearsLegendLength - 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]
-
K. Biermann over 3 years@DakshGargas No, it does not make it the same. If you use
unowned
you say "Don't create a reference cycle – butself
will always be alive when you access this closure". A hypothetical example would be: InstanceA
privately owns a closureC
which capturesA
itself. So you need weak or unowned to avoid a retain cycle. However sinceC
is private it cannot be called ifA
does not exist anymore, soself
can never benil
. -
Daksh Gargas over 3 years@K.Biermann then why not use
weak self
? To save oneself from theself != nil
check? -
K. Biermann over 3 years@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). -
Daksh Gargas over 3 years@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 :)
-
Andrey Zhukov about 3 years@DakshGargas
unowned
is also faster thanweak
(it doesn't create side table for heap object) -
Daksh Gargas about 3 years@AndreyZhukov wow... I didn't know that part!! Thanks, man!
-
Eric over 2 years
weak someVarName
is tosomeVarName?
asunowned someVarName
is tosomeVarName!
...In other words, if you use "unowned", you better be sure it isn't nil. -
daniel about 2 yearsAm 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
-
daniel about 2 yearsI would like to know the answer to the question right above by @mfaani.
-
daniel about 2 yearsAm 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? -
SafeFastExpressive almost 2 yearsunowned 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.