[self] is new term which we can use in blocks to avoid usage of self keyword. Then how is this different from [weak self]? Does [self] takes cares of retain cycle?
I couldn't find much info on this so any simple example with explanation will be highly appreciated.
[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.
Related
I have massive memory leaks in the project I am currently working on. The VC's never disappear from the memory and unfortunately that causes many, many problems right now. The only culprit that I can think of is the way I use closures in the name of readability and simplicity since none of those closures captures self strongly inside. The way I use is as following:
functionWithEscapingClosure(closure: functionGivenToTheClosure(_:))
If this creates a strong reference I have soo many refactoring to do, if not I will look elsewhere. Thanks in advance!
I have looked for an explanation to the subject online, searched through the Swift documentation but couldn't find any information.
Your snippet there is essentially equivalent to:
functionWithEscapingClosure(closure: { parameter in
self.functionGivenToTheClosure(parameter)
})
So yes, it would implicitly capture a strong reference to the instance that owns the function passed in.
You would need to explicitly do the weak capture to break the cycle:
functionWithEscapingClosure(closure: { [weak self] parameter in
self?.functionGivenToTheClosure(parameter)
})
I see a lot of code like this:
DispatchQueue.main.async {
self.tableView.reloadData()
}
In this context, where tableView is a property of self, should one instead ensure weak self is captured like this:
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
I think so, but this type of "unsafe" code is so ubiquitous across codebases I wonder if I'm missing something?
You said:
In this context, where tableView is a property of self, should one instead ensure weak self is captured like this:
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
No, you don’t actually need to use weak reference to self in this case. There is no persistent strong reference cycle here. The worst that would happen (in the absence of weak reference) is that it will keep a strong reference to self until the dispatched block finishes running. But that closure will generally run practically immediately and the fleeting strong reference will be eliminated very quickly.
So, as such, no, you don’t have to use weak reference here. It is not technically incorrect to do so, but adds a syntactic noise for practically no benefit. Yes, we should be diligent about breaking potential strong reference cycles with weak references, but this is not one of those cases.
By the way, the choice of the term “unsafe” muddles the topic a bit. “Unsafe” has a very specific meaning when talking about memory references: It generally refers to dangling references to deallocated objects when not using runtime safety checks. As The Swift Programming Language: Automatic Reference Counting says (emphasis from original):
Swift also provides unsafe unowned references for cases where you need to disable runtime safety checks—for example, for performance reasons. As with all unsafe operations, you take on the responsibility for checking that code for safety.
You indicate an unsafe unowned reference by writing unowned(unsafe). If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation.
Obviously, both strong and weak references are safe (the former keeps the object from being released, the latter sets its references to nil when the object is deallocated). Even unowned references often employ runtime safety checks (though it still results in runtime error if you use a unowned reference after the object is deallocated). An “unsafe” reference is used in high-performance scenarios, where you are absolutely confident in your unowned references are being handled properly and that you’re willing to run your code without runtime safety checks.
I suspect you didn’t mean “unsafe” in this context, but I mention it so that you are aware of the very specific meaning that this word has within the context of ARC and memory management.
I'm trying to explain ownership of objects and how GCD does its work.
These are the things I've learned:
a function will increase the retain count of the object its calling against
a dispatch block, unless it captures self weakly will increase the count.
after a dispatched block is executed it release the captured object, hence the retain count of self should decrease. But that's not what I'm seeing here. Why is that?
class C {
var name = "Adam"
func foo () {
print("inside func before sync", CFGetRetainCount(self)) // 3
DispatchQueue.global().sync {
print("inside func inside sync", CFGetRetainCount(self)) // 4
}
sleep(2)
print("inside func after sync", CFGetRetainCount(self)) // 4 ?????? I thought this would go back to 3
}
}
Usage:
var c: C? = C()
print("before func call", CFGetRetainCount(c)) // 2
c?.foo()
print("after func call", CFGetRetainCount(c)) // 2
A couple of thoughts:
If you ever have questions about precisely where ARC is retaining and releasing behind the scenes, just add breakpoint after “inside func after sync”, run it, and when it stops use “Debug” » “Debug Workflow” » “Always Show Disassembly” and you can see the assembly, to precisely see what’s going on. I’d also suggest doing this with release/optimized builds.
Looking at the assembly, the releases are at the end of your foo method.
As you pointed out, if you change your DispatchQueue.global().sync call to be async, you see the behavior you’d expect.
Also, unsurprisingly, if you perform functional decomposition, moving the GCD sync call into a separate function, you’ll again see the behavior you were expecting.
You said:
a function will increase the retain count of the object its calling against
Just to clarify what’s going on, I’d refer you to WWDC 2018 What’s New in Swift, about 12:43 into the video, in which they discuss where the compiler inserts the retain and release calls, and how it changed in Swift 4.2.
In Swift 4.1, it used the “Owned” calling convention where the caller would retain the object before calling the function, and the called function was responsible for performing the release before returning.
In 4.2 (shown in the WWDC screen snapshot below), they implemented a “Guaranteed” calling convention, eliminating a lot of redundant retain and release calls:
This results, in optimized builds at least, in more efficient and more compact code. So, do a release build and look at the assembly, and you’ll see that in action.
Now, we come to the root of your question, as to why the GCD sync function behaves differently than other scenarios (e.g. where its release call is inserted in a different place than other scenarios with non-escaping closures).
It seems that this is potentially related to optimizations unique to GCD sync. Specifically, when you dispatch synchronously to some background queue, rather than stopping the current thread and then running the code on one of the worker threads of the designated queue, the compiler is smart enough to determine that the current thread would be idle and it will just run the dispatched code on the current thread if it can. I can easily imagine that this GCD sync optimization, might have introduced wrinkles in the logic about where the compiler inserted the release call.
IMHO, the fact that the release is done at the end of the method as opposed to at the end of the closure is a somewhat academic matter. I’m assuming they had good reasons (or practical reasons at least), to defer this to the end of the function. What’s important is that when you return from foo, the retain count is what it should be.
After reading some articles and developer guide of apple, i'm still confused about Capture List in closure.
What does it mean "capture", how does it work behind the scene in terms of unowned self and weak self? how the closure use self without owning the object?
I thought it like making a copy of that object so when it get finished it's passed from the stack like value type, but i guess that i'm wrong.
I'm hoping that someone here can make it more easier and clear for understanding, or linked me to a good article that answering this specific question.
Thanks for advance
My understanding, and it might be a bit simplified, is that it is about ownership and holding on to an object, meaning that as long as we claim ownership of an object it can not be freed from memory even another part of the code sets it to nil or similar.
With weakwe say that it is okay to destroy the object and that we will only use it if it is still around.
So when declaring self as weak in a closure we say that if self is still around when it's time to execute the closure we do so normally otherwise the closure will silently be ignored without generating an error.
It's mainly to do with reference counting. Any instance that is used inside a closure (but was declared outside) is strongly referenced (i.e. its reference count is incremented). This can lead to retain cycles, e.g.
class MyClass {
var myClosure: (() -> Void)!
init() {
myClosure = {
self.foo()
}
}
func foo() {
}
}
In the above example the instance of MyClass retains a reference to myClosure and vice versa, meaning that the MyClass instance will stay in memory forever.
You can also have more complex/harder-to-spot retain cycles, so you need to really pay attention and if you ever have any doubts add some print calls to your class' deinit methods just to make sure (or use Instruments).
In order to avoid these issues you can mark objects being captured in closures as unowned or weak. This means that their reference count won't be increased and you can avoid these retain cycles. The above example could have either been done this way:
myClosure = { [weak self] in
self?.foo()
}
or, better yet for this example, this way:
myClosure = { [unowned self] in
self.foo()
}
While the first way is always safe and what you will more likely do, the unowned version is easy to reason in this example because you know that myClosure won't outlive self. However, if you're not 100% sure that self will always outlive the closure use weak.
Also note that you can mark how to capture multiple objects used inside the closure, just separate it by commas, e.g.
myClosure = { [weak self, unowned bar] in
self?.foo(bar)
}
If we keep in mind that captured values are strong references in closures by default, we can assume that this can create retain cycles (bad stuff).
A capture list is an array of variables you can pass into a closure. The purpose of capture lists is to change the strenght of the variables that are passed in. This is used to break retain cycles.
For instance:
// strong reference
[label = self.myLabel!] in
// weak reference
[weak label = self.myLabel!] in
// unowned reference
[unowned self] in
I want self to be non-nil and I'm sure it will be, during the blocks execution. So why explicitly specify [unowned self] ?
object.executeBlock {
date = self.lastModified
}
vs
object.executeBlock { [unowned self] in
date = self.lastModified
}
Edit:
Well i'm getting down votes so let's try again. Q: Let’s say I have a problem. That problem is that I would like to prevent a reference cycle. I have two options. I could use [unowned self] or I could use [weak self]. My question therefore, is this: from these two options, why would I choose [unowned self] ? Why not choose [weak self] everytime ?
"The Language Guide claims you should use unowned if the closure and containing object reference each other and will be destroyed at the same time. Presumably that's to avoid the cost of safely nil'ing out a weak reference in an object that's about to dealloc anyway."
http://www.russbishop.net/swift-capture-lists
So [unowned self] makes self an an implicitly unwrapped optional, for the convenience of not unwrapping it yourself, at the risk of a crash if of course it is actually nil.
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.
Do you have a strong reference cycle there?
I answered this elsewhere. Here's the Cliff notes:
If self could be nil in the closure use [weak self].
If self will never be nil in the closure use [unowned self].
If it's crashing when you use [unowned self] I would guess that self is nil at some point in that closure, which is why you had to go with [weak self] instead.
I really liked the whole section from the manual on using strong, weak, and unowned in closures:
https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html
Why [unowned self]?
self points to object, object has executeBlock, and executeBlock points back to self, creating a memory cycle.
However when you say [unowned self]: the system will not keep self in memory in order to to make the closure work. it will assume that self is always there when the closure is executed.
If not for some reason, there won't be undefined behavior or anything like that but your app will crash as it is a runtime error.
This is how it was explained by Paul Hegarty, stanford iOS dev teacher.
In a situation where self could conceivably be nil at the time it's used in the closure, you're compelled to use weak semantics (or risk a crash).
In a case where you can reason that self will never be nil, you can choose to specify either: "choose" in the sense that both are correct and will work. Arguably one could be considered "more correct" than the other, in the sense that both semantics satisfy the requirements but one is more specific.
Two reasons you might want to specified unowned instead of self:
Convenience
Documentation
An unowned reference will be more convenient to use because it doesn't need to be unwrapped. It may also be more efficient, since the compiler may not have to produce as much cleanup code for safe deallocation.
In terms of documentation, you're making a kind of assertion about something your program believes to be true. If that assumption (assuming it was valid) is violated, you may like to find out about it in the form of a crash.
Subsequently, this may also make usage of the variable less exhausting: you think about it and document your reasoning that it must always exist up front, and then each time you use it, you don't have to expend further mental energy wondering "what do I do if this isn't here?".
Arguably, using a let binding or guard statement also achieves the latter.