How to quit "DispatchQueue.main.asyncAfter" in Swift - ios

I want to quit "DispatchQueue.main.asyncAfter" when deinit is called.
subView.swift
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
self.doSomething()
}
func doSomething(){
if self.subView.flgA == false { //error because subView's deinit is already called
//...
}
}
When ViewController do _ = self.navigationController?.popViewController(animated: true) and deinit is called, deinit in ViewController and subView is called at first and after a few minutes doSomething() is called.
I want to stop doSomething() when popViewController is executed.
How can I do it?

You could schedule a Timer with this code block
let timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] timer in
self?.doSomething()
}
hold on to the timer and cancel it before popViewController like this:
timer.invalidate()
Notice the [weak self] and the self?.domeSomething() which I put there to avoid the hard reference to the viewcontroller and read Laffen's more detailed answer on this.

In Swift we have something called ARC(Automatic Reference Counting).
ARC will make sure any object with at least one strong reference to it, will not be removed from memory.
In your case you're creating a strong reference to self in the closure of the async task created by DispatchQueue.main.asyncAfter.
You need to tell the compiler that this reference is either weak or unowned(See attached link for more info.), this will enable the instance of self to be deinitialised even though you have a reference to self from the closure.
The weak keyword can be used in cases where you want the closure to run and make actions that doesn't require a reference to self. This is helpful to use if you don't know if self is alive or not.
The unowned keyword can be used in cases where you don't need the closure to run without a reference to self. This must be used in cases where you know self self is still alive.
Getting a weak or unowned reference of self in the closure can be achieved like in the example below:
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[weak self] in
self?.doSomething()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[unowned self] in
self.doSomething()
}
It's worth mentioning that if you're not using a deadline, but calling .async { ... } directly does not result in capturing self and therefore can be used safely without defining weak/unowned self.

Related

UIView.animate() : do I need a weak reference to self in the animation block? [duplicate]

This question already has answers here:
Is it necessary to use [unowned self] in closures of UIView.animateWithDuration(...)?
(7 answers)
Closed 2 years ago.
After some research I found out my app was using way too much energy because of several UIView animations throughout the app, where I was capturing the related UIViewController in the completion block, without making a weak reference to it.
So actually, I changed this:
func animate() {
UIView.animate(withDuration: 0.3, animations: {
self.label.alpha = 0.5
}) { _ in
self.animate()
}
}
Into this :
func animate() {
UIView.animate(withDuration: 0.3, animations: {
self.label.alpha = 0.5
}) { [weak self] _ in
self?.animate()
}
}
However, I would like to know if I need to do the same with the animation block (the self.label.alpha = 0.5 one) ?
Thank you for your help
No, it is not needed in this case. animations and completion are not retained by self so there is no risk of strong retain cycle.
duplicated of Is it necessary to use [unowned self] in closures of UIView.animateWithDuration(...)?
You don't need to use [weak self] in UIView.animate(). You need to use weak when retain cycle is possible and animations block is not retained by self.
There is an article on medium about where [weak self] may and may not be needed
For more information:
Automatic Reference Counting
Closures
There might be another issue for the energy problem.
What do you mean by:
my app was using way too much energy
I don't see any immediate relation between keeping a weak reference on your view controller and saving energy.
Capturing self without increasing its retain count in your closure (that's what we mean by having a weak reference on an object) means that if no other strong reference on your view controller exists, then your view controller will be released sooner. Maybe you will save some RAM in a very short term.
I would suggest to investigate somewhere else to find where your "energy" issue comes from.
There are a lot of articles about the use of weak keyword.
https://medium.com/flawless-app-stories/you-dont-always-need-weak-self-a778bec505ef
Sure, you do need to use the "weak self" concept there.
In fact note: it is indeed very common in that situation that a VC is trashed during an animation ... so indeed, it's one of the places you "most need" to use the weak-self idea. It's a very common mistake in projects to forget that in an animation.
By the way, here's a handy syntax any time you need weak self:
func animate() {
UIView.animate(withDuration: 0.3, animations: { [weak self] in
guard let self = self else { return print("gotchya!") }
self.label.alpha = 0.5
}) { [weak self] in
guard let self = self else { return print("gotchya!") }
self.animate()
}
}
Adding this line ..
guard let self = self else { return }
.. can seem a bit long-winded, but, it means you then don't need the "?"
after "self" every time you use it in long blocks.
Often you will have many uses of "self ..." inside such a block, and it seems more consistent to just use the "let self = self" idiom.
So even if there is only one line of code in the block (as in your two examples) it's a good way to be absolutely consistent everywhere and keep things simple.
Note that whenever you have a { return } you can just add a print statement so that you know what is going on during development ..
.... { [weak self] in
guard let self = self else { return print("I avoided a crash, woot!") }
or
.... { [weak self] in
guard let self = self else { return print("logical disaster near line 66") }
You do not have to do that, "{ return }" is fine. It's just for your convenience.
What the hell is this "self = self" business?
If you find the "self = self" idiom confusing ....... honestly, just don't worry about it. Always use that idiom. It's really just the "standard" thing you will see everywhere.
Always go for simple consistency in your code base!
More weak self mysteries ...
Here's a interesting QA from a handsome list member: Where does the weak self go?
And later there's this sort of confusion to worry about: What is the difference between a weak reference and an unowned reference?

What is the meaning of following swift code?

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

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.

Resources