How do I dispatch_sync, dispatch_async, dispatch_after, etc in Swift 3, Swift 4, and beyond?
Since the beginning, Swift has provided some facilities for making ObjC and C more Swifty, adding more with each version. Now, in Swift 3, the new "import as member" feature lets frameworks with certain styles of C API -- where you have a data type that works sort of like a class, and a bunch of global functions to work with it -- act more like Swift-native APIs. The data types import as Swift classes, their related global functions import as methods and properties on those classes, and some related things like sets of constants can become subtypes where appropriate.
In Xcode 8 / Swift 3 beta, Apple has applied this feature (along with a few others) to make the Dispatch framework much more Swifty. (And Core Graphics, too.) If you've been following the Swift open-source efforts, this isn't news, but now is the first time it's part of Xcode.
Your first step on moving any project to Swift 3 should be to open it in Xcode 8 and choose Edit > Convert > To Current Swift Syntax... in the menu. This will apply (with your review and approval) all of the changes at once needed for all the renamed APIs and other changes. (Often, a line of code is affected by more than one of these changes at once, so responding to error fix-its individually might not handle everything right.)
The result is that the common pattern for bouncing work to the background and back now looks like this:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.imageView.image = image
}
}
Note we're using .userInitiated
instead of one of the old DISPATCH_QUEUE_PRIORITY
constants. Quality of Service (QoS) specifiers were introduced in OS X 10.10 / iOS 8.0, providing a clearer way for the system to prioritize work and deprecating the old priority specifiers. See Apple's docs on background work and energy efficiency for details.
By the way, if you're keeping your own queues to organize work, the way to get one now looks like this (notice that DispatchQueueAttributes
is an OptionSet
, so you use collection-style literals to combine options):
class Foo {
let queue = DispatchQueue(label: "com.example.my-serial-queue",
attributes: [.serial, .qosUtility])
func doStuff() {
queue.async {
print("Hello World")
}
}
}
Using dispatch_after
to do work later? That's a method on queues, too, and it takes a DispatchTime
, which has operators for various numeric types so you can just add whole or fractional seconds:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
print("Are we there yet?")
}
You can find your way around the new Dispatch API by opening its interface in Xcode 8 -- use Open Quickly to find the Dispatch module, or put a symbol (like DispatchQueue
) in your Swift project/playground and command-click it, then brouse around the module from there. (You can find the Swift Dispatch API in Apple's spiffy new API Reference website and in-Xcode doc viewer, but it looks like the doc content from the C version hasn't moved into it just yet.)
See the Migration Guide for more tips.
Swift 2 to 3 Migration dispatch_get_global_queue
Try this it will work.
DispatchQueue.global(qos: .background).async {
DispatchQueue.main.async {
}
})
If you still need any help feel free to ask here.
dispatch_async in Swift
You can use this syntax:
dispatch_async(dispatch_get_main_queue(), {
println("hello")
})
However, when the last argument is a block, Swift lets you put it outside the parentheses. This makes the function seem more like a control structure (like a for
or if
statement). Thus you can do this:
dispatch_async(dispatch_get_main_queue()) {
println("hello")
}
translate dispatch_async in swift
The swift 3 syntax is
DispatchQueue.main.async {
//your code
}
iOS - Is possible to combine Swift 3 and Swift 4 code within one project?
If you're using CocoaPods to manage your 3rd party dependencies then yes you can. The Swift version can be set in the Build Settings for the pod target in the pod project.
So you can have an app running Swift 4 that uses libraries built for Swift 3.2 fine.
If you're adding the 3rd party libs to your main project then it might not be possible, although you could extract the libs into their own projects (or private cocoapods) and add to your workspace and set the Swift version on each individually
And Xcode should have a warning prompting you to convert to Swift 4 which you can click, which should convert your project to Swift 4 automatically but you may end up having to fix some warnings/errors manually
Queues and Swift 3 issue
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 {
}
dispatch_async vs dispatch_sync in fetch data. Swift
GCD provides queues for executing tasks. Queues can be of two types – concurrent or serial. In serial queue tasks execute one at time (in FIFO order), in concurrent queue several tasks at time.
To prevent user fetch data while one fetch task is running, it is needed to not submit fetch task to queue at this moment. No matter what kind of queue is it – concurrent or serial.
var array = [Int]()
var isFethingData = false
func fetchData() {
if !isFethingData {
isFethingData = true
dispatch_async(queueForFetchData) {
…
response(objects: [object], error: NSError?) {
for object in objects {
array.append(object.number)
}
dispatch_async(dispatch_get_main_queue()) {
makeCollectionView()
}
isFethingData = false
}
}
}
dispatch_async
and dispatch_sync
is functions which submits tasks to queue. The difference is that dispatch_async
return immediately after task has been submitted, but dispatch_sync
wait until task complete. For example:
print("\(NSDate()) qq")
dispatch_sync(queue) {
// … some code which runs for 10 minutes.
print("\(NSDate()) ee")
}
print("\(NSDate()) ww")
// 2016-08-18 16:02:00 qq
// 2016-08-18 16:12:00 ee
// 2016-08-18 16:12:00 ww
print("\(NSDate()) qq")
dispatch_async(queue) {
// … some code which runs for 10 minutes.
print("\(NSDate()) ee")
}
print("\(NSDate()) ww")
// 2016-08-18 16:02:00 qq
// 2016-08-18 16:02:00 ww
// 2016-08-18 16:12:00 ee
Where do I need to use dispatch_async on main_queue?
- dispatch_get_main_queue() function will return the main queue where your UI is running.
- The dispatch_get_main_queue() function is very useful for updating the iOS app’s UI as UIKit methods are not thread safe (with a few exceptions) so any calls you make to update UI elements must always be done from the main queue.
for more see this link
https://www.hackingwithswift.com/read/9/4/back-to-the-main-thread-dispatch_get_main_queue
Related Topics
How to Enumerate an Enum With String Type
How to Store 1.66 in Nsdecimalnumber
Firestore Search Array Contains For Multiple Values
Uialertcontroller - Add Custom Views to Actionsheet
Can Swift Convert a Class/Struct Data into Dictionary
Swift Alamofire: How to Get the Http Response Status Code
Storing Values in Completionhandlers - Swift
Nsfilemanager Fileexistsatpath:Isdirectory and Swift
How to Accomplish Where in Query in Cloud Firestore
Do Swift-Based Applications Work on Os X 10.9/Ios 7 and Lower
How to Get a Reference to the App Delegate in Swift
Send Data from Tableview to Detailview Swift
Checking If an Object Is a Given Type in Swift
What Does "@Uiapplicationmain" Mean
Can You Execute an Applescript Script from a Swift Application