how to stop a dispatchQueue in swift
I'm not sure if there are best practices here, but I would consider doing what you are doing with a Timer rather than the DispatchQueue.
class GifClass: UIViewController {
@IBOutlet weak var gifImage: UIImageView!
@IBOutlet weak var skipButton: UIButton!
var timer = Timer()
override func viewDidLoad() {
super.viewDidLoad()
gifImage.loadGif(name: "promed")
timer = Timer.scheduledTimer(timeInterval: 11, target: self, selector: #selector(timerAction), userInfo: nil, repeats: false)
}
@objc func timerAction() {
performSegue(withIdentifier: "introLogin", sender: self)
}
@IBAction func skip(_ sender: Any) {
timer.invalidate()
performSegue(withIdentifier: "introLogin", sender: self)
}
}
Swift Cancel DispatchQueue Process
There is no way to stop or "kill" a DispatchWorkItem
or NSOperation
from outside. There is a cancel()
method, but that merely sets the isCancelled
property of the item or operation to true. This does not stop the execution of the item itself. Ans since recv
is blocking, there is no way to check the isCancelled
flag during execution. This means the answer posted by Vadian unfortunately wouldn't do anything.
According to the Apple docs on NSOperation.cancel
:
This method does not force your operation code to stop.
The same goes for NSOperationQueue.cancelAllOperations
:
Canceling the operations does not automatically remove them from the queue or stop those that are currently executing.
You might think it is possible to drop down to using a raw NSThread
. However, the same principle applies hier. You cannot deterministically kill a thread from the outside.
Possible solution: timeout
The best solution I can think of is to use the timeout feature of the socket. I don't know where UDPServer
comes from, but perhaps it has a built in timeout.
Possible solution: Poor man's timeout (send packet to localhost)
Another option you can try is to send some UDP packets to yourself after a certain time has elapsed. This way, recv
will receive some data, and execution will continue. This could possibly be used as a "poor man's timeout".
Stop a DispatchQueue that is running on the main thread
You can use DispatchWorkItem
s. They can be scheduled on DispatchQueue
s and cancelled before their execution.
let work = DispatchWorkItem(block: {
self.isShootingOnHold = false
self.shoot()
self.shootingEngine = Timer.scheduledTimer(timeInterval: (Double(60)/Double(self.ratePerMinute)), target: self, selector: #selector(ShootingEnemy.shoot), userInfo: nil, repeats: true)
})
DispatchQueue.main.asyncAfter(deadline: .now() + (delay * Double(isDelayAccounted.hashValue)) + extraDelay, execute: work)
work.cancel()
How to quit DispatchQueue.main.asyncAfter in Swift
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
.
Unable to stop DispatchQueue.global().async task on swift
Issue has been resolved, actually should't have used dispatch global async in first place. Tried doing it with a timer and it worked, vibrating after each secs and it doesn't freeze the UI, also gets stopped easily after just calling timer.invalidate(). Thanks for the help guys :)
Is there a way to cancel a DispatchQueue concurrentPerform operation?
DispatchQueue.concurrentPerform
causes the block to be executed the specified number of times, and waits for all iterations to complete. There is no way to prevent that. (The blocks run in parallel if the target queue is a concurrent queue.)
Of course each work item can “early return” if some condition is met, but that won't affect the other work items.
Your code crashes because leave()
is called on the dispatch group more times than enter()
.
Related Topics
How to Declare Exponent/Power Operator with New Precedencegroup in Swift 3
Swift Optional Type: How .None == Nil Works
How to Use Navigation in Alert Using Swiftui
Nstableview Get Indexpath Having the Cell
How to Return a Value from a Void Closure in Swift
Swift, for Some Uiviews to Their Overall Controller When Clicked
Attributed Text, Replace a Specific Font by Another Using Swift
Why Is Casting a Struct to Anyobject Not a Compile Error in Swift
How to Use Implicitly Unwrapped Optionals
Observe Progress of Data Download in Swift
Dismiss View from View Model [Modal Page]
How Set Custom Fonts for iOS13 Context Menu Actions
Possible to Write Swift Println Logs into File Too
Get the First Day of Week Without Weekcalendarunit
How to Handle Parameter Validation Swift
Crash When Running on Device After Second Launch