Where does the weak self go? - swift

I often do this,
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
beep()
}
and in one app we often do this
tickle.fresh(){
msg in
paint()
}
but if you do this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
msg in
paint()
}
}
of course you have to do this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
msg in
self?.paint()
}
}
or, maybe this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
or maybe this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
W T H should we do?
All three suggestions seem to work perfectly. What's the full depth of meaning here? And which should one do? Is a strong reference to a weak reference, a weak or strong reference? To be or not to be? That's the question!

First of all, note that you generally don't need to worry about retain cycles with DispatchQueue.main.asyncAfter, as the closure will be executed at some point. Therefore whether or not you weakly capture self, you won't be creating a permanent retain cycle (assuming that tickle.fresh also doesn't).
Whether or not you put a [weak self] capture list on the outer asyncAfter closure depends entirely on whether you want self to be retained until the closure is called (after the time you set). If you don't need self to remain alive until the closure is called, put [weak self] in, if you do, then don't put it in.
Whether or not you put a [weak self] on the inner closure (the one passed to tickle.fresh) depends on whether you've already weakly captured self in the outer closure. If you haven't, then you can put [weak self] in order to prevent the inner closure from retaining it. If however, the outer closure has already weakly captured self, then the inner closure will already have a weak reference to self, thus adding [weak self] to the inner closure will have no effect.
So, to summarise:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { msg in
self.paint()
}
}
self will be retained by both the outer and inner closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { msg in
self?.paint()
}
}
self will not be retained by either closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { [weak self] msg in
self?.paint()
}
}
Same as the above, the additional [weak self] for the inner closure has no effect, as self is already weakly captured by the outer closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { [weak self] msg in
self?.paint()
}
}
self will be retained by the outer closure, but not the inner closure.
Of course, it might be that you don't want self to be retained by the outer closure, but you do want it to be retained by the inner closure. In such cases, you can declare a local variable in the outer closure in order to hold a strong reference to self, when you can then capture in the inner closure:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
guard let strongSelf = self else { return }
tickle.fresh { msg in
strongSelf.paint()
}
}
Now, self won't be kept alive by the outer closure, but once it's called, if self still exists, it will be kept alive by the inner closure until that closure has been deallocated.
In response to:
Is a strong reference to a weak reference, a weak or strong reference?
Weak references are implemented as optionals, which are value types. Therefore you cannot directly have a strong reference to one – instead you first have to unwrap it, and then take a strong reference to the underlying instance. In this case you're simply dealing with a strong reference (exactly like my example above with strongSelf).
However, if a weak reference is boxed (this happens with closure capture – the value type will be put into a heap-allocated box) – then you can indeed have a strong reference to that box. The effect of this is equivalent to a weak reference to the original instance, you just have an invisible bit of extra indirection.
In fact, this is exactly what happens in the example where the outer closure weakly captures self and the inner closure 'strongly captures' that weak reference. The effect is that neither closure retains self.

Related

Why am I getting a retain cycle from passing weak self in to a static function's closure?

My AchievementViewController does not get released from memory unless I comment out the function below
NetworkConnection.achievementList(for: -1) { [weak self] response in
guard let sections = response.object as? [AchievementListSection] else {
return print("Network failure")
}
self?.sections = sections
self?.configureCollectionView()
}
The definition for this function is below where at present we just use a delayed async call to send a stubbed response.
static func achievementList(for identifier: Int64, responseHandler: RequestResponseClosure?) {
let stubResponse = ResponseObject(object: AchievementListSection.exampleList as NSArray, code: .success)
let randomDelayMilliseconds = Int(arc4random_uniform(1000))
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(randomDelayMilliseconds)) {
responseHandler?(stubResponse)
}
}
Where exactly is self being retained to create a cycle here? It's passed in to the NetworkConnection closure as a weak reference and in turn when this closure is passed to DispatchQueue I would expect it to release after the delay has passed.
try comment this line
self?.configureCollectionView()
mb it's the problem, because [weak self] is enough for fix retain in this closure

Broadcast 'weak self' to escaping block [duplicate]

I often do this,
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
beep()
}
and in one app we often do this
tickle.fresh(){
msg in
paint()
}
but if you do this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
msg in
paint()
}
}
of course you have to do this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
msg in
self?.paint()
}
}
or, maybe this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
or maybe this
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
W T H should we do?
All three suggestions seem to work perfectly. What's the full depth of meaning here? And which should one do? Is a strong reference to a weak reference, a weak or strong reference? To be or not to be? That's the question!
First of all, note that you generally don't need to worry about retain cycles with DispatchQueue.main.asyncAfter, as the closure will be executed at some point. Therefore whether or not you weakly capture self, you won't be creating a permanent retain cycle (assuming that tickle.fresh also doesn't).
Whether or not you put a [weak self] capture list on the outer asyncAfter closure depends entirely on whether you want self to be retained until the closure is called (after the time you set). If you don't need self to remain alive until the closure is called, put [weak self] in, if you do, then don't put it in.
Whether or not you put a [weak self] on the inner closure (the one passed to tickle.fresh) depends on whether you've already weakly captured self in the outer closure. If you haven't, then you can put [weak self] in order to prevent the inner closure from retaining it. If however, the outer closure has already weakly captured self, then the inner closure will already have a weak reference to self, thus adding [weak self] to the inner closure will have no effect.
So, to summarise:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { msg in
self.paint()
}
}
self will be retained by both the outer and inner closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { msg in
self?.paint()
}
}
self will not be retained by either closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { [weak self] msg in
self?.paint()
}
}
Same as the above, the additional [weak self] for the inner closure has no effect, as self is already weakly captured by the outer closure.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { [weak self] msg in
self?.paint()
}
}
self will be retained by the outer closure, but not the inner closure.
Of course, it might be that you don't want self to be retained by the outer closure, but you do want it to be retained by the inner closure. In such cases, you can declare a local variable in the outer closure in order to hold a strong reference to self, when you can then capture in the inner closure:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
guard let strongSelf = self else { return }
tickle.fresh { msg in
strongSelf.paint()
}
}
Now, self won't be kept alive by the outer closure, but once it's called, if self still exists, it will be kept alive by the inner closure until that closure has been deallocated.
In response to:
Is a strong reference to a weak reference, a weak or strong reference?
Weak references are implemented as optionals, which are value types. Therefore you cannot directly have a strong reference to one – instead you first have to unwrap it, and then take a strong reference to the underlying instance. In this case you're simply dealing with a strong reference (exactly like my example above with strongSelf).
However, if a weak reference is boxed (this happens with closure capture – the value type will be put into a heap-allocated box) – then you can indeed have a strong reference to that box. The effect of this is equivalent to a weak reference to the original instance, you just have an invisible bit of extra indirection.
In fact, this is exactly what happens in the example where the outer closure weakly captures self and the inner closure 'strongly captures' that weak reference. The effect is that neither closure retains self.

Confusion about where should put the [unowned self]

I have a retained cycle so my viewcontroller's deinit won't be called, and I'm trying to resolve this my adding [unowned self], but I'm not too sure where to put the unowned in my cases:
Case 1
class YADetailiViewController: UIViewController {
var subscription: Subscription<YAEvent>?
override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
query, object in
DispatchQueue.main.async {
[unowned self] in// Put unowned here won't break the cycle, but it does compile and run
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}
}
Case 2
override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
[unowned self] query, object in // Put unowned breaks the cycle, and deinit is called
DispatchQueue.main.async {
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}
I'm curious what's the differences between these two scenarios and why one works but not the other
Indeed, as correctly mentioned by #matt the problem is related to the time when self is captured. In fact int this code self is captured twice:
When the outer closure is passed to the handle method
When the inner closure is passed to the async method (during the handle closure execution)
The outer closure needs self to pass it to the inner closure, otherwise the inner closure won't be able to capture it.
The nature or retain cycle is the following: self(YADetailiViewController) -> subscription -> closure (handle parameter) -> self. To break this cycle it's enough to not retain self in that (outer) closure. That's why the second code sample works.
The second capture of self (in the inner closure) happens only when the outer closure is executed and lasts until that async block is executed - usually it's quite a short time.
In the first code sample you're not breaking the cycle. The second capture of self doesn't happen but the first one (causing thy cycle) is still present.
And if your handle closure can still be called when the view controller is already deinited/released then as suggested by #AdrianBobrowski you should use weak instead of unowned to prevent possible crash.

When we should NOT use neither [weak self] nor [unowned self]?

I've read several discussion on StackOverflow about when we should use [weak self] or [unowned self] in closures.
However, are there any cases when we don't have to use neither of them since Swift doesn't show any error or warning when we're just explicitly using self inside a closure.
For example, should we use weak or unowned here?
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0.0
}
You need to use [weak self] or [unowned self] if your closure can cause a Strong Reference Cycle.
This can occur if you assign the closure to a property of self and you refer to self or a property of self inside the closure itself. Closures are reference types, hence essentially the same rules apply to strong references as if you used normal classes.
As for your example, there is no need for [weak self] or [unowned self], since you don't assign the closure to a variable inside the class to which self refers to, so there won't be a strong reference cycle.
For more information, check out the Strong Reference Cycles for Closures part of the Swift programming language guide. Here is an example from the mentioned link of when a strong reference cycle can be caused by closures:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
Without [unowned self] in the closure of asHTML, a strong reference cycle will be caused by the closure assigned to asHTML. Changing the implementation of asHTML to the following solves this issue:
lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
This is somewhat opinion based, so I'll give my opinion :)
I generally base it on synchronicity. If a closure is Async, the calling instance may no longer exist when the closer is called and therefore [weak self] should be used. If a closure is synchronous, it's unnecessary and capturing a strong reference is fine.
This could be expanded to also include closures where you can reasonably expect your instance to remain valid when it's called (e.g. your View animation case), however be aware this makes an assumption that the closure and your usage of it will remain unchanged, so it could theoretically break at some point in the future. This less safe and makes future maintenance more difficult/dangerous.
In the case of an established and predictable API like UIView.animate, I personally tend to use strong self for the sake of brevity, but that's an evaluation you'll need to do yourself and it depends on the usage.
Also as noted in the comments, this is true of function-closures. Assigning a closure to another variable's property has a different set of issues.
As an aside, I have adopted the approach of weak-reference closures simply calling another method in my Type, e.g.
thing.doSomethingWithAClosure() { [weak self]
self?.doSomething()
}
It simplifies the logic while also enforcing more functional/modular code.

self refrence inside swift closure return nil some time

I am accessing instance method inside closure in swift, self reference become nil in some cases which result crash my program. I tried to access using [weak self] but it failed to call the instance method when self is nil.
[weak self] () -> () in
The whole point of [weak self] is to not create a reference to self (probably to avoid circular links and memory leaks) so that it can be released. If that happens, then self will be nil.
You should either not use [weak self] or, better yet probably, be prepared to handle the case of self having been released and set to nil.
guard let strong = self else { return }
Take the example:
import UIKit
import PlaygroundSupport
class Foo {
let name : String
init(name:String) {
self.name = name
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
print(self!.name)
}
}
}
Foo(name:"freddie")
PlaygroundPage.current.needsIndefiniteExecution = true
In this case, you'll get a crash, because self is released before the async callback is made.
You can either change the asyncAfter call to be:
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
print(self.name)
}
will guarantee that self isn't released until after the callback is made.
Or you can use something like:
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
guard let strong = self else { print("self released") ; return }
print(strong.name)
}
I am able to fix this issue by making strong instance while creating it, in my case this weak variable was making nil to self. Thanks all for providing suggestion for my queries.