Why [weak self] is not required for #nonescaping closure? [duplicate] - ios

This question already has answers here:
Shall we always use [unowned self] inside closure in Swift
(11 answers)
Closed 3 years ago.
According to https://stackoverflow.com/a/38144190/72437
The reason is that the immediately applied closure {}() is considered
#noescape. It does not retain the captured self.
and https://oleb.net/blog/2016/10/optional-non-escaping-closures/
However, it’s impossible to create a reference cycle with a
non-escaping closure — the compiler can guarantee that the closure
will have released all objects it captured by the time the function
returns.
However, I still do not understand why #nonescaping closure does not retain self, and doesn't require [weak self]? Can someone explain this concept in simpler manner?

The closure does not need to retain self, because the closure itself only lives as long as the function that created it (and self won't go away as long as one of its own functions is still running). So there is no need to keep anything around for longer than the function invocation itself.
You only need to retain something in order to make sure it exists for (at least) as long as you yourself exist (or need access to that thing).
If the closure was escaping the scope of the function that created it, then it could not rely on any of the things it got from that function's scope being kept alive after the function returned. So it has to retain these things itself.

A non-escape closure tells the complier that the closure you pass in will be executed within the body of that function so do not need to use weak self.

Related

UICollectionview.performBatchUpdates updates block does not need explicit use of self in capture list

When using collectionview.performBatchUpdates, the updates block does not need explicit self like below image.
The method's docs are here. https://developer.apple.com/documentation/uikit/uicollectionview/1618045-performbatchupdates
My guesss is that performBatchUpdates's updates block life cycle is garanteed shorter than collectionView. And the updates block called using withoutActuallyEscaping.
Is there anyone have clear answer?
The answer is simple. Because it's not a escaping closure
The animate closure is escaping, while the performBatchUpdates closure is not.
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write #escaping before the parameter’s type to indicate that the closure is allowed to escape
An escaping closure that refers to self needs special consideration if self refers to an instance of a class. Capturing self in an escaping closure makes it easy to accidentally create a strong reference cycle. For information about reference cycles, see Automatic Reference Counting.
Normally, a closure captures variables implicitly by using them in the body of the closure, but in this case you need to be explicit. If you want to capture self, write self explicitly when you use it, or include self in the closure’s capture list. Writing self explicitly lets you express your intent, and reminds you to confirm that there isn’t a reference cycle.

How different #escpaing closure are stored in memory compare to #nonescaping [duplicate]

This question already has answers here:
Swift function object wrapper in apple/swift
(1 answer)
How are escaping closures implemented in Swift 3 (under the hood)? Are they implicitly block_copied/retained like in objective-c?
(1 answer)
Closed 5 years ago.
I feel a bit confused, trying to understand, how #escaping closures are working.
As far as I understand
An escaping closure is a closure that’s called after the function it was passed to returns. In other words, it outlives the function it was passed to.
But how that closure is stored in the memory. Are they located in stack or in heap? How do they refer to the function it was passed? And what the key difference in comprising with #nonescaping.
Think of an escaping block as code that jumps back to where the function was called originally. Meaning, if you have this method which executes the escaping block if variable is set to "yes":
func thisMethodHasA(variable: String, withAn escaping: #escaping (()->())) {
if variable == "yes" {
escaping()
//this will execute the code in the brackets
}
//this will return the method
}
and you call it like so (in playgrounds):
thisMethodHasA(variable: "no") {
print("the bracket code is executed")
}
print("thisMethodHasNowFinished")
the printed result is:
thisMethodHasNowFinished
As you see, the code is never executed.
If we set it to "yes":
thisMethodHasA(variable: "yes") {
print("the bracket code is executed")
}
print("thisMethodHasNowFinished")
the bracket code is executed
thisMethodHasNowFinished
As you see, the code inside the brackets was run before the method ended it's course.
So really, escaping blocks are pointers to code which only allocates a potential reference of memory space for that escaping block.. but without actually allocating that space until the escaping block is called. So i would say that escaping blocks are referenced similarly to how class references are performed to minimize memory allocation. So what your referenced sentence means, is that the code in escaping blocks keep a singular pointer throughout the app cycle, unlike a method pointer, which is deallocated whenever it's run it's course. By this definition, i'd suggest that it is stored in the stack, not the heap (to address your question).
I found these links/posts and articles which seem to get to a close answer too:
https://stackoverflow.com/a/41257089/7183483
For a good read on how Swift manages both Stack and Heap allocation:
https://medium.com/#itchyankles/memory-management-in-rust-and-swift-8ecda3cdf5b7
this one also explains the logic behind alocation.. so perhaps there is some hinting here at how these blocks are managed.. again, seems to be a lack of solid documentation on this topic out there!

Block/Closure Understanding

Need clarification on blocks and closure.
How blocks will retain the object? or why we need to use only weak inside block? What will happen if we don't follow this? Or please give some clarity on block.
The below one os for closure.
I have written some code like this. favouriteButton is a property of self.
favouriteButton.hidden = false
dispatch_async(dispatch_get_main_queue(), {
self._collectionView.reloadData()
})
It didn't gave any error. So I thought of doing UI in main thread. So I moved the code to disable hidden inside block like below.
dispatch_async(dispatch_get_main_queue(), {
favouriteButton.hidden = false
self._collectionView.reloadData()
})
It shows an error like
reference to property 'favouriteButton' in closure requires explicit
'self'
dispatch_async(dispatch_get_main_queue(), {
self.favouriteButton.hidden = false
self._collectionView.reloadData()
})
Could any one please explain how to use closure/block effectively.
Does the blocks and closures work in the same way?
In Swift (and Objective-C), a block is a closure. The term closure refers to an individually-executable block of code that captures the values of variables in the enclosing scope. In the case of Swift, the enclosing scope is usually a function, and only variables used within the block are captured.
The reason you need to preface class-level references (properties and function calls) with self. is to make explicit the capturing of self. Doing so allows you to specify how self (or any other object reference) is captured: strong (default) or weak.
There are two reasons to be careful with retaining objects (keeping strong references) within a block.
The most common concern is creating a retain cycle. This is where the block retains a strong reference to an object, which in turn has a strong reference to the block. Until one of the references is explicitly broken, neither the block, nor the object, will be released. (Releasing a block simply cleans up the captured variables. The executable code remains.)
A strong reference to an object within a block can keep the object alive longer than intended. For example, if a block keeps a reference to a view controller that is popped off a navigation stack, you likely don't want that block to act on the view controller when its executed. This can be avoided by capturing a weak reference to the view controller. This allows the view controller to be deallocated when it's popped, and the block becomes a no-op.

Can I trigger a compiler warning when there is an implicitly captured "self" in Swift

If I have some code that takes a closure, and self is implicitly captured, can I make it cause a compiler warning? Is there some flag I can add to the compiler command for this?
Not exactly. But there is something that addresses what's presumably the reason you'd want this warning — to prevent situation where a closure capturing self can cause a retain cycle...
The potential retain cycle from capturing self in a closure comes up when the closure is passed as a parameter to a function but is used after the function returns — that is, the lifetime of the closure (and anything captured in it) "escapes" the context in which it's written. When the closure escapes, it has to be sure it still has access to the things it uses (like self and any properties or methods thereof), so we get into memory management and possible retain cycles, [weak self]/strongSelf, etc.
With #noescape, you can declare that closures passed as parameters to a function will not escape the calling context, and as such don't require the extra memory management overhead for closures that do. And the compiler can apply some other optimizations that make running your function and its closure faster.
func someFunctionWithNoescapeClosure(#noescape closure: () -> Void) {
closure()
}
Within a #noescape closure, you can then access methods/properties on self without explicitly writing self., because you're not capturing self anymore. And, once you label a parameter #noescape, if you try to do anything that would permit it to escape (say, take the closure from the parameter and assign it to a stored property), you'd get a compiler error (not just a warning).
For the full writeup from Apple, see Nonescaping Closures in The Swift Programming Language. And this post provides an alternate perspective that might explain things further.
No, the only thing I can think of which can do anything similar is linting.
SwiftLint might be able to do something like that, and if not you can probably write your own rule for just such a thing.

When is self deallocated while dismissing view controller

I have a question regarding memory deallocation and blocks/closures.
Following is the Swift method
self!.dismissViewControllerAnimated(false, completion: {
println(self);
})
Or the objective C method
[self dismissViewControllerAnimated:NO completion:^{
NSLog("%#",self);
}];
I would really appreciate if anyone could explain when in the above method self would be deallocated . Is it after the completion block is run or before that? I understand its taken care by ARC but I would like to know if self gets release message in the completion block or after that. Hence, if I do some minor clean up in the completion block (accessing self), is that safe/acceptable or not?
There are really two separate questions to understand the answer completely:
1. When Are Variables Referenced Inside of Closures Released?
You can think of a closures as just another type (in Swift they really are). Every closure creates a strong ownership over the variables referenced inside of it, including self. This ensures that you never reference a variable that has been deallocated. Just like in any other object, when the closure gets deallocated, it releases its ownership over all of its variables.
If the closure is the only thing with a strong reference to that a variable, the variable will be dealloced when the closure is dealloced.
So in short, variables stay in memory as long as the closure is still in memory.
2. When Are Closures Deallocated?
Now the second part of this that is important to understand, is when does a closure get dealloced. You could store a closure in a variable:
func myMethod() {
var myClosure = {
println(self)
}
myClosure()
}
In this case, the closure has a strong reference from its variable myClosure and the closure has a strong reference to self. As soon as myClosure goes out of scope, i.e. when myMethod exits, it will be dealloced. When that happens, self will be released.
You may also have a situation, like in your question, where you are passing a closure into another method. In this case, the method you are passing the closure into is capturing a strong reference to your closure. When that method exits, it will release your closure, the closure will be deallocated, and it will release all variables captured inside it.
The Exception
Sometimes it is necessary to define a closure that does not take ownership over a variable. You would do this to avoid circular references. You can read more in Apple's documentation on what a circular reference is and how to prevent them here. However, it is important to realize that unless you put in explicit effort (and code), closures will always capture strong references to variables referenced inside of it.
In Swift, while developing/debugging and trying to understand the timing of operations, you can add the following to your View Controllers (or any class), to track if or when the instance is a about to deallocated.
Although that won't help you detect 'strong reference cycles' described here:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
deinit {
println(__FUNCTION__, "\(self)")
}

Resources