When to Use [Self] VS [Weak Self] in Swift Blocks

What is difference between [self] in & [weak self] in in Swift?

Writing [self] is same as leaving the closure as it is meaning it could cause retain cycle unlike [weak self] , BTW no need for any of them with DispatchQueue.main.async { as GCD queues don't hold a strong reference to self

When to use [self] vs [weak self] in swift blocks?

[self] indicates that self is intentionally held with a strong reference (and so some syntax is simplified). [weak self] indicates that self is held with a weak reference.

why would I use strong capture [self] inside block as there are chances of memory leak

You would use this when you know there is no reference cycle, or when you wish there to be a temporary reference cycle. Capturing self does not by itself create a cycle. There has to be a cycle. You may know from your code that there isn't. For example, the thing holding the closure may be held by some other object (rather than self). Good composition (and decomposition of complex types into smaller types) can easily lead to this.

Alternately, you may want a temporary cycle. The most common case of this URLSessionTask. The docs are very valuable here (emphasis added):

After you create a task, you start it by calling its resume() method. The session then maintains a strong reference to the task until the request finishes or fails; you don’t need to maintain a reference to the task unless it’s useful for your app’s internal bookkeeping.

Another common example is DispatchQueue, which similarly holds onto a closure until it finishes. At that point, it releases it, killing the cycle and allowing everything to deallocate. This is useful and powerful (and common!), when used with intent. It's a source of bugs when used accidentally. So Swift requires you to state your intentions and tries to make the situation explicit.

When you build your own types that retain completion handlers, you should strongly consider this pattern, too. After calling the completion handler, set it to nil (or {_ in } for non-optionals) to release anything that completion handler might be referencing.

One frustrating effect of the current situation is that developers slap [weak self] onto closures without thought. That is the opposite of what was intended. Seeing self was supposed to cause developers to pause and think about the reference graph. I'm not certain it ever really achieved this, but as a Swift programmer you should understand that this is the intent. It's not just random syntax.

Is it the right way using `[weak self]` in swift closure?

Your pattern has race condition. If self was deallocated at the exact same time as your completion handler closure was executing, it could crash. As a general rule, avoid using the ! forced unwrapping operator if you can.

  1. I’d lean towards the guard “early exit” pattern (reducing nested braces, making code easier to read). The standard Swift 4.2 solution is:

    someTask { [weak self] result in
    guard let self = self else { return }

    self.xxx = yyy
    self.doLongTermWork()
    self.finish()
    }
  2. Before Swift 4.2, which implemented SE-0079, we would have to do something like:

    someTask { [weak self] result in
    guard let strongSelf = self else { return }

    strongSelf.xxx = yyy
    strongSelf.doLongTermWork()
    strongSelf.finish()
    }

    You can see why we prefer the Swift 4.2 improvement, as this strongSelf syntax is inelegant.

  3. The other obvious alternative is just:

    someTask { [weak self] result in
    self?.xxx = yyy
    self?.doLongTermWork()
    self?.finish()
    }

    Sometimes you need the “weak self - strong self dance” (the first two alternatives), but it would not appear to be the case here. This is likely sufficient.

There are other scenarios/edge cases that one might contemplate, but these are the basic approaches.

Weak self vs self when using closure defined in swift in objective c

First of all try to understand what is a retaincycle and how it will affect your application..

A retain cycle is a condition that happens when two objects keeps strong reference to each others.

Sample Image

In such cases these objects won't get deallocated and it will stay in memory forever and leads to memory leak.

Retain cycle in blocks and why should we use weakself

Closures and blocks are independent memory objects and they will retain the objects they reference so if we are accessing any class variable or method inside the closure or block using self then there is a chance for retain cycle

self.myBlock = ^{ self.someProperty = xyz; }; // RETAIN CYCLE

will get this warning

Capturing 'self' strongly in this block is likely to lead to a retain
cycle

To avoid such situation we should weakSelf to access members

__weak typeof(self) weakSelf = self;

`self.myBlock = ^{ weakSelf.someProperty = xyz; };`

So there is a rule like always use weakSelf in blocks but there are some special cases like animation blocks

[UIView animateWithDuration:duration animations:^{ [self.superview layoutIfNeeded]; }];

Here we can use self inside the block because the blocks get destroyed automatically once animation completed.

Should I use [weak self] if I don't actually reference self in my completion block?

Capturing the variables, happens only when you use it internally, a closure will NEVER capture the variables by default (not like Java inner class which ALWAYS captures this), so, it you use a variable (including self) inside the closure, it is captured.

Also you can manually capture the variables using the [weak self], [weak your_variable_here], [unowned self], [unowned your_variable_here], [self] or [your_variable_here]

If the compiler tells you variable "self" is written to but never read from, it means that you didn't use self inside, so it is completely safe not to use [weak self], because self will NOT be captured, because it is not used.

weak self or unowned self is needed only when your closure captures self, and escapes the function it is passed to, especially if it is saved in a variable.

Refer to Closures in Apple's Official Swift Documentation

Difference between weak self vs weak self()

You do not pass [weak self] () as an argument to a closure.

  • [weak self] is a capture list and precedes the
  • parameter list/return type declaration () -> Void

in the closure expression.

The return type or both parameter list and return type can be omitted if they can
be inferred from the context, so all these are valid
and fully equivalent:

dispatch_async(dispatch_get_main_queue()) { [weak self] () -> Void in 
self?.doSomething()
}

dispatch_async(dispatch_get_main_queue()) { [weak self] () in
self?.doSomething()
}

dispatch_async(dispatch_get_main_queue()) { [weak self] in
self?.doSomething()
}

The closure takes an empty parameter list () and has a Void
return type.

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

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

In Swift, if I have a closure capturing [weak self], is it good practice to unwrap the optional self at the beginning of the closure?

I believe that the first implementation is better because self could become nil between the statements

And that's why the second implementation is in fact better! If self is not nil at the first statement, the first statement makes it so that self couldn't become nil between the statements. It retains self exactly for the remainder of the block. This is called "the weak–strong dance".

guard let self = self else { return }
// ^^^^ this self is _strong_, not weak; it retains self

Do we need to repeat `guard let self = self else { return }` inside each nested closure to keep strong self?

Yes, one is enough.
If you write

guard let self = self else { return }

you'll create a new local variable that will hold a strong reference to the outside weak self.

It's the same as writing

guard let strongSelf = self else { return }

and then use strongSelf for the rest of the block.



Related Topics



Leave a reply



Submit