What is the meaning of following swift code? - ios

Can anyone tell me why we use guard let self = self ??
I have seen this code while reading about GCD, I couldn't figure out what that particular line does.
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self = self else {
return
}
// ...
}

First you are creating a block that will be executed asynchronously
DispatchQueue.global(qos: .userInitiated).async
Then inside the block the code checks if self, the object that is calling this function, is still allocated
guard let self = self else {
return
}
We need to check this because self is declared as weak inside the block to avoid a retain cycle (Swift closures causing strong retain cycle with self) and can be deallocated before the block is executed. That line of code checks if self is != nil, and assign it to self, otherwise it returns.

self is declared weak in this block, so it has an Optional type. E.g. if the name of your class is MyViewController then the type of self in that block is MyViewController?. The reason for the use of weak is to avoid retain cycles. The block should only execute if self is still alive. So one solution would be:
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.makeFoo()
strongSelf.continueWithBar()
}
but there is no need to call it strongSelf. You can call it self too. The self variable after the guard block is actually a different variable than self, it just has the same name.
So the meaning is:
Execute this block only if self is still alive. (Otherwise, do nothing.)

The code inside async {} will b executed asynchronously. The completion function ({ [weak self] ... }) contains a (default strong) reference to the object calling the async function.
Since it is asynchronous you don't have a way to know a) when the callback will be executed b) if it will be executed. Meaning that the strong reference to self could cause a memory leak.
That is why one uses [weak self] to pass a weak reference. Since the call is async, it can be that, when the callback is finally executed, the ARC has already collected the reference to self and thus self would be nil.
It is then good to check if self still exists before executing the code in the callback.

A thread is being created and added to global queue and has QOS(Quality of service or you can say priority of that thread) user initiated(medium priority) after that you execute set of instructions async

Related

ARC Retain Cycles, Grand Central Dispatch and Closures

I understand that if you assign a closure to a property such as:
var someClosure : () -> Void?
let someConstant : Int = 5
And call that closure from its class' init with a reference to self:
someClosure = { print(self.someConstant) }
Then this will result in a retain cycle, so I should use weak to avoid it.
But I couldn't understand the following code which is from a raywenderlich.com tutorial:
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self = self else {
return
}
self.someFunction()
}
Why a retain cycle exists here - since we didn't create a reference from view to closure (i.e., saving closure as a property) but only from closure to self; shouldn't it be retain cycle-free?
You are right and Ray is wrong:
Grand Central Dispatch closures don't cause retain cycles.
You can delete
[weak self] in
guard let self = self else {
return
}
Please see also https://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/

Should I weakify "local" variables used in a block?

This is not another question about [weak self]. This is about use of variables not contained by self, but rather by the wrapping function.
func someFunction(){
someOtherFunction(completionBlock:{ [weak self] in
self?.doStuff()
})
}
As far as I understand, I need the [weak self] in order to prevent a retain cycle.
But what if I need to use a variable from the wrapping function, like this:
func someFunction(){
let someVariable = MyObject()
someOtherFunction(completionBlock:{ [weak self] in
self?.doStuff(with: someVariable)
})
}
This works, which makes me wonder.. How, and how long is someVariable held in memory? Can it create its own tiny retain cycle where my completion block strongly references the local someVariable? How will they be released? Should I add [weak self, weak someVariable] in the block? But then, won't someVariable be released immediately after I call someOtherFunction, because it's the end of this function - and the end of someVariable's lifetime..?
I'm having trouble completely understanding references, and can't see how my completionBlock and someVariable will ever be released.. Are blocks even released?
Any variable referenced inside a closure will be strongly retained by that closure. You can adjust that by including a closure capture list (e.g. [weak self]), which allows you to specify the particular memory management pattern of references captured in the closure.
func someFunction(){
let someVariable = MyObject()
someOtherFunction(completionBlock:{ [weak self] in
self?.doStuff(with: someVariable)
})
}
Here, someVariable is retained by the closure, as you have stated. In this case, it has to be, because nobody else cares about it. As you've mentioned in comments, if you used a capture list of [weak someVariable] then it would always be nil when the completion block executed, as it has gone out of scope in it's original function.
A "tiny retain cycle" isn't being created. A retain cycle has to be a cycle - that is, A holds a strong reference to B, which holds a strong reference to A. someVariable doesn't have references to anything.
Once someOtherFunction has finished with the reference to the completion closure, everything goes away. The closure is just another variable as far as someOtherFunction is concerned, and it will survive as long as it is in scope.
Should I weakify “local” variables used in a block? - no, as they will then be nil by the time the block comes to use them.
I would like to mention not so clear option, what is very usual place to create retain cycle and where you should be aware of weaken variables.
Lets consider this situation:
func someFunction() {
let object = Something()
object.handler = { [weak self] in
self?.doStuff(with: object)
}
}
Now there is retain cycle, and object cannot be deallocated until somebody manually unset the handler. Because now object strongify itself in the captured block.
So better solution is:
func someFunction() {
let object = Something()
object.handler = { [weak self, unowned object] in
self?.doStuff(with: object)
}
}
And good practice is pass the object as argument in handler
func someFunction() {
let object = Something()
object.handler = { [weak self] (object) in
self?.doStuff(with: object)
}
}
So signature of this should look like:
class Something {
var handler:((Something) -> Void)?
deinit {
print("retain cycle is not here")
}
}

What happens to Dispatch Queues when UIViewController is Deallocated?

I am trying to better understand retain cycles, especially relative to Dispatch Queues. I am working with AVFoundation and managing an AVCaptureSession on a sessionQueue:
private let sessionQueue = DispatchQueue(label: "com.andrewferrarone.sessionQueue")
in a lot of code examples in the apple documentation I see this:
self.sessionQueue.async { [unowned self]
//
}
Is the [unowned self] self here necessary? self (the viewController) references self.sessionQueue and the closure dispatched to self.sessionQueue captures self. Is this a reference cycle? self is not referencing the closure, just the DispatchQueue. If [unowned self] is necessary, then from what I understand, I only want to use unowned self if I am certain that self will not be nil. So lets say I put a task on sessionQueue that takes a long time and the viewController gets popped off and is deallocated before the task finishes? What happens to sessionQueue and the task? If its still around then, when it tries to access self, the app will crash. On the other hand, since unowned self doesn't increment the retain count of self, then it won't prevent the viewController from being deallocated.
So My question is what happens to DispatchQueues when a viewController is deallocated and what happens in this case, if a viewController gets deallocated before a dispatchQueue task is finished? If someone could shed some light on what all is going on here that would be very helpful and appreciated.
Thanks for the help my friends!
Is the [unowned self] self here necessary?
Not only is the use of [unowned self] not necessary, but it's very dangerous in an asynchronously dispatched block. You end up with a dangling pointer to a deallocated object.
If you don't want to keep keep a strong reference to self in an asynchronous call, use [weak self], instead. You should only use unowned if you know the block can never be called after self is deallocated. Obviously, with async call, you don't know this, so [unowned self] should not be used in that context.
Whether you use [weak self] or use strong references is a question of whether you need the asynchronously executed block to keep a strong reference to the object in question or not. For example, if you're updating a view controller's view's controls only, then [weak self] is fine (no point in updating a view that has been dismissed).
The more critical use of weak and unowned references is to avoid strong reference cycles. But that doesn't apply in the example you've provided. You only need to worry about those cycles if the view controller keeps some reference to the blocks itself (e.g. you have some closure property) and those closures reference self, but without a weak/unowned qualifier.
My question is what happens to DispatchQueues when a view controller is deallocated?
Those queues will continue to exist, as will any dispatched blocks, until (a) all dispatched blocks finish; and (b) there are no more strong references to the queue.
So if you asynchronously dispatch blocks with weak references to self (i.e. the view controller), they will continue to run after the view controller is released. This is why it's critical to not use unowned in this context.
For what it's worth, empirical tests can be illuminating. Consider:
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let queue = DispatchQueue(label: "com.domain.app.SecondViewController")
for i in 0 ..< 10 {
queue.async { [weak self] in
print("closure \(i) start")
self?.performSomeTask(i)
print("closure \(i) finish")
}
}
}
private func performSomeTask(_ value: Int) {
print("performSomeTask starting \(value)")
Thread.sleep(forTimeInterval: 5) // you wouldn't generally `sleep`, but merely for diagnostic purposes
print("performSomeTask finishing \(value)")
}
deinit {
print("deinit SecondViewController")
}
}
If you dismiss this view controller while the dispatched blocks are queued up and running, you'll see:
With [weak self], the view controller is retained only until the current dispatched block finishes, the view controller will then be released, and the rest of the blocks will rapidly fire off, but because of [weak self], the performSomeTask won't run after the view controller is dismissed.
If you replace weak with unowned (and obviously remove the ? in self?.performSomeTask(...)), you'll see it crash if you dismiss the view controller before the queued blocks have had a chance to start. This is illustrative of why [unowned self] is so dangerous with asynchronous code.
If you simply remove [weak self] altogether and let it use a implicitly strong reference to self, you'll see it won't deallocate the view controller until all queued blocks finish.

SCNAction block preventing memory deallocation

I've got this code that makes a reference to self in a SCNAction block in the following way:
spawnAction = SCNAction.runBlock({ node in
dispatch_async(dispatch_get_main_queue(),{
[weak self] in
if let actualSelf = self {
actualSelf.spawnDelegate?.spawnRiverCrosser(node.position)
}
})
})
When I set this class to nil, my deinit method is not called. It is called through if I comment out the line
actualSelf.spawnDelegate?.spawnRiverCrosser(node.position)
I read about the retain cycle and I do understand that the method won't be called if I have any strong reference hanging around, but as many StackOverflow answers suggest, by using the closure [weak self] the problem should be solved. I don't get why it is not working.

Correct placement of capture list in nested closures in swift

Where do I define captured references for nested closures in Swift?
Take this code as an example:
import Foundation
class ExampleDataSource {
var content: Any?
func loadContent() {
ContentLoader.loadContentFromSource() { [weak self] loadedContent in
// completion handler called on background thread
dispatch_async(dispatch_get_main_queue()) { [weak self] in
self?.content = loadedContent
}
}
}
}
class ContentLoader {
class func loadContentFromSource(completion: (loadedContent: Any?) -> Void) {
/*
Load content from web asynchronously,
and call completion handler on background thread.
*/
}
}
In this example, [weak self] is used in both trailing closures, however the compiler is perfectly happy if I omit [weak self] from either one of the trailing closures.
So that leaves me 3 options for defining my capture list:
define captures on every nested closure leading up to the reference
define captures on the first closure only.
define captures on only the most nested closure that actually uses the reference.
My question is:
If I know that my ExampleDataSource could be nil at some point, what is the best option to go with?
It is important to note that GCD dispatch_async will NOT cause a retain cycle. In other words, when the block has finished executing, GCD will not retain any references made within the block.
The same is not true for strong references between classes, or strong references within a closure assigned to a property of an instance. Apple Documentation
That being said, in this example, the correct answer is option 2, to define captures on the first closure only.
For testing purposes I modified the code slightly:
class ExampleDataSource {
init() {
print("init()")
}
deinit {
print("deinit")
}
var content: Any?
func loadContent() {
print("loadContent()")
ContentLoader.loadContentFromSource() { [weak self] loadedContent in
dispatch_async(dispatch_get_main_queue()) {
print("loadedContent")
self?.content = loadedContent
}
}
}
}
class ContentLoader {
class func loadContentFromSource(completion: (loadedContent: Any?) -> Void) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)) {
sleep(5) // thread will hang for 5 seconds
completion(loadedContent: "some data")
}
}
}
First I create, var myDataSource: ExampleDataSource? = ExampleDataSource().
Then I run myDataSource.loadContent().
Before the completion handler gets a chance to run, I set myDataSource = nil, removing all references to it.
The debug console indicates that a reference to self was not retained:
init()
loadContent()
deinit
loadedContent
Looks like we found our answer! But just for completion's sake, let's test the alternatives...
If [weak self] is instead captured on only the inner most trailing closure, GCD will retain ExampleDataSource until the block has finished executing, which explains why the debug would instead look like this:
init()
loadContent()
loadedContent
deinit
The same thing will happen if no capture list is included and we never optionally unwrapped self, although the compiler, does try to warn you!
While it isn't technically incorrect to include [weak self] captures in all trailing closures, it does detract from the readability of code and doesn't feel very 'Swift-like'.

Resources