GCD stop with cancellable_dispatch_after [duplicate] - ios

This question already has answers here:
Stop a DispatchQueue that is running on the main thread
(2 answers)
Closed 4 years ago.
Grand Central Dispatch (GCD) function they can utilize but once it's set up, these calls can not be easily cancelled.
How could we stop it such as a custom method "cancellable_dispatch_after"

If you are trying to find a way to cancel asynchronous operations using GCD, you should use DispatchWorkItem. It allows you to do the following:
import Dispatch
let task = DispatchWorkItem {
//Do some stuff
}
DispatchQueue.main.async(execute: task)
task.cancel()
Obviously, you wouldn't do this exactly, but I believe it shows how to do what you want.
Hope this helps!

Related

Need to call API's asynchronously and update the UI immediately instead of waiting for all the API to complete in Swift [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 months ago.
Improve this question
I have a PLP page, I need to hit stock API for all the products visible in screen, and Need to update the stock UI for each product once received the response for every product, I have implemented this using Dispatch Semaphore but faced crash when navigating between screens and I tried using Operation queue but in that I am getting the response at cumulative time of all the API hits. Even I tried with Dispatch group, it also responds same as Operation queue.
One API is taking around half second so each product stock should be updated in half to 1 second is what I need, Any help appreciated.
Tried code using Operation Queue
var queue: OperationQueue?
queue = OperationQueue()
queue?.qualityOfService = .background
productListView.sendCBRClosure = { [unowned self] cbrCodeArray in
queue?.maxConcurrentOperationCount = 5
for cbrCode in cbrCodeArray {
queue?.addOperation {
self.getStockDetail(cbrCode: cbrCode) // API call
}
}
}
Tried code using Dispatch Semaphore
var semaphore = DispatchSemaphore(value: 4)
productListView.sendCBRClosure = { [weak self] cbrCodeArray in
DispatchQueue.global().async { [weak self] in
for cbrCode in cbrCodeArray {
//API call
self?.getStockDetail(cbrCode: cbrCode) { qtyStr in
self?.semaphore.signal() // after API response received
}
self?.semaphore.wait()
}
Apple's networking calls using URLSession already run asynchronously on a background thread. There's no reason to need operation queues, DispatchQueue, etc.
Just submit a separate request for each item, and have the response handling code update the UI in a call to the main thread. (You can't do UIKit calls from a background thread.)
Each network operation will run separately and invoke it's completion handler once it's done.

Queues and Swift 3 issue [duplicate]

This question already has answers here:
How do I dispatch_sync, dispatch_async, dispatch_after, etc in Swift 3, Swift 4, and beyond?
(6 answers)
Closed 6 years ago.
Please help me to convert this line to swift 3.0:
dispatch_async(DispatchQueue.global(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0))
And what does it exactly mean? Something like: do the code in brackets in the main queue?
Thanks in advance.
ps. This line of code was taken from apple's code to work with core data
In Swift 3 You can write like this
DispatchQueue.global(qos: .background).async {
}
It means what every the code written in between the bracket will perform in the background. and if you want to make any changes in this background thread you have to switch to the main thread. by writing the block below.
dispatch_async(dispatch_get_main_queue()) {
// Your code for UI Changes.
}
EDIT: Swift 3
DispatchQueue.main.async {
}
One of the most common task in Grand Central Dispatch (GDC) pattern is performed work on a global background queue and update the UI on the main queue as soon as the work is done.The new API looks like this:
DispatchQueue.global(attributes: [.qosDefault]).async {
// Background thread
DispatchQueue.main.async(execute: {
// UI Updates
})
}
Queues now take attributes on init. This is a Swift optionSet and can include queue options such as serial vs concurrent, memory and activity management option and the quality of service (.default, .userInteractive, .userInitiated, .utility and .background).
New changes:
DISPATCH_QUEUE_PRIORITY_HIGH: -> .userInitiated
DISPATCH_QUEUE_PRIORITY_DEFAULT: -> .default
DISPATCH_QUEUE_PRIORITY_LOW: -> .utility
DISPATCH_QUEUE_PRIORITY_BACKGROUND: -> .background
if you want to learn more about, this is a good talk https://developer.apple.com/videos/play/wwdc2016/720/

asynchronous Swift function taking long time to update label [duplicate]

I'm beginner swift developer. I'm stucked with this weather app.I'm downloading website data and then displaying in my label.
Unfortunately this whole process takes like 10 second to update my label.
This is probably not because of the network connection as the console is updated instantly.
Thanks for suggestions.
What happens is that code is probably run on a secondary thread. Any UI changes you make should be made on the main thread. So try this:
dispatch_async(dispatch_get_main_queue()) {
// update label
}
This should update your label instantly.
Previously, we would choose the dispatch method (sync vs async) and then the queue we wanted to dispatch our task to. The updated GCD reverses this order - we first choose the queue and then apply a dispatch method.
Swift 3:
Now in Swift 3 the GCD library was updated like in the following way:
DispatchQueue.main.async(execute: {
// UI Updates
})
I hope this help you.
It might be late to answer but in Swift 3 logic should be like this.
DispatchQueue.global(qos: .background).async {
// Background Thread Or Service call Or DB fetch etc
DispatchQueue.main.async {
// Run UI Updates and other logic
}}
Your code has multiple issues.
FIRST: It has strong reference cycle
Fix it by putting this in closure.
[weak weakSelf = self]
SECOND: Update UI in main thread
DispatchQueue.main.async {
//Update UI
weakSelf?.mReslut.text = ""
}

cancel dispatch_after() method? [duplicate]

This question already has answers here:
Prevent dispatch_after() background task from being executed
(11 answers)
Closed 8 years ago.
Is there a way to cancel dispatch_after() scheduled for some time in future, and haven't fired so far?
I'm trying to make something like a scheduler for updates from server, and this method is just like I want, but, I'd love to cancel and re-schedule it at some point.
Is it possible at all or I have to fallback and use NSTimer?
There is NO way to prevent a dispatch_block from executing once it has been dispatch to it's queue, meaning that your dispatch_after cannot be canceled. Only option is to add in your block a condition to be checked at runtime to prevent execution.
ie.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^ {
if(self.shouldExecuteDispatchBlock)
{ // do your stuff } });
OK, so, with all answers collected, and possible solutions, seems like the best one for this case (preserving simplicity) is calling performSelector:withObject:afterDelay: and cancelling it with cancelPreviousPerformRequestsWithTarget: call when desired. In my case - just before scheduling next delayed call:
[NSObject cancelPreviousPerformRequestsWithTarget: self selector:#selector(myDelayedMethod) object: self];
[self performSelector:#selector(myDelayedMethod) withObject: self afterDelay: desiredDelay];
For this purpose i used this class:
https://github.com/SebastienThiebaud/dispatch_cancelable_block
you can call a cancel() function to revoke the execution of what's in the block.
Use a dispatch timer source (that is what dispatch_after uses internally anyway).
A dispatch timer source can be canceled or its timer parameters changed after creation.

Updating label takes too long (swift)

I'm beginner swift developer. I'm stucked with this weather app.I'm downloading website data and then displaying in my label.
Unfortunately this whole process takes like 10 second to update my label.
This is probably not because of the network connection as the console is updated instantly.
Thanks for suggestions.
What happens is that code is probably run on a secondary thread. Any UI changes you make should be made on the main thread. So try this:
dispatch_async(dispatch_get_main_queue()) {
// update label
}
This should update your label instantly.
Previously, we would choose the dispatch method (sync vs async) and then the queue we wanted to dispatch our task to. The updated GCD reverses this order - we first choose the queue and then apply a dispatch method.
Swift 3:
Now in Swift 3 the GCD library was updated like in the following way:
DispatchQueue.main.async(execute: {
// UI Updates
})
I hope this help you.
It might be late to answer but in Swift 3 logic should be like this.
DispatchQueue.global(qos: .background).async {
// Background Thread Or Service call Or DB fetch etc
DispatchQueue.main.async {
// Run UI Updates and other logic
}}
Your code has multiple issues.
FIRST: It has strong reference cycle
Fix it by putting this in closure.
[weak weakSelf = self]
SECOND: Update UI in main thread
DispatchQueue.main.async {
//Update UI
weakSelf?.mReslut.text = ""
}

Resources