How to use threading in swift?

dispatchOnMainThread:^{ NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue())); }]; 
5

17 Answers

Swift 3.0+

A lot has been modernized in Swift 3.0. Running something on a background queue looks like this:

DispatchQueue.global(qos: .userInitiated).async { print("This is run on a background queue") DispatchQueue.main.async { print("This is run on the main queue, after the previous code in outer block") } } 

Swift 1.2 through 2.3

let qualityOfServiceClass = QOS_CLASS_USER_INITIATED let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0) dispatch_async(backgroundQueue, { print("This is run on a background queue") dispatch_async(dispatch_get_main_queue(), { () -> Void in print("This is run on the main queue, after the previous code in outer block") }) }) 

Pre Swift 1.2 – Known issue

As of Swift 1.1 Apple didn't support the above syntax without some modifications. Passing QOS_CLASS_USER_INITIATED didn't actually work, instead use Int(QOS_CLASS_USER_INITIATED.value).

For more information see Apples documentation

8

Dan Beaulieu's answer in swift5 (also working since swift 3.0.1).

Swift 5.0.1

extension DispatchQueue { static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) { DispatchQueue.global(qos: .background).async { background?() if let completion = completion { DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: { completion() }) } } } } 

Usage

DispatchQueue.background(delay: 3.0, background: { // do something in background }, completion: { // when background job finishes, wait 3 seconds and do something in main thread }) DispatchQueue.background(background: { // do something in background }, completion:{ // when background job finished, do something in main thread }) DispatchQueue.background(delay: 3.0, completion:{ // do something in main thread after 3 seconds }) 
7

The best practice is to define a reusable function that can be accessed multiple times.

REUSABLE FUNCTION:

e.g. somewhere like AppDelegate.swift as a Global Function.

func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) { dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) { background?() let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(popTime, dispatch_get_main_queue()) { completion?() } } } 

Note: in Swift 2.0, replace QOS_CLASS_USER_INITIATED.value above with QOS_CLASS_USER_INITIATED.rawValue instead

USAGE:

A. To run a process in the background with a delay of 3 seconds:

 backgroundThread(3.0, background: { // Your background function here }) 

B. To run a process in the background then run a completion in the foreground:

 backgroundThread(background: { // Your function here to run in the background }, completion: { // A function to run in the foreground when the background thread is complete }) 

C. To delay by 3 seconds - note use of completion parameter without background parameter:

 backgroundThread(3.0, completion: { // Your delayed function here to be run in the foreground }) 
9

In Swift 4.2 and Xcode 10.1

We have three types of Queues :

1. Main Queue: Main queue is a serial queue which is created by the system and associated with the application main thread.

2. Global Queue : Global queue is a concurrent queue which we can request with respect to the priority of the tasks.

3. Custom queues : can be created by the user. Custom concurrent queues always mapped into one of the global queues by specifying a Quality of Service property (QoS).

 thread DispatchQueue.global(qos: .userInitiated)// High Priority DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated) DispatchQueue.global(qos: .background)//Lowest Priority DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low) DispatchQueue.global(qos: .utility)//Low Priority DispatchQueue.global(qos: .unspecified)//Absence of Quality 

These all Queues can be executed in two ways

1. Synchronous execution

2. Asynchronous execution

DispatchQueue.global(qos: .background).async { // do your job here DispatchQueue.main.async { // update ui here } } //Perform some task and update UI immediately. DispatchQueue.global(qos: .userInitiated).async { // Perform task DispatchQueue.main.async { // Update UI self.tableView.reloadData() } } //To call or execute function after some time DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { //Here call your function } //If you want to do changes in UI use this DispatchQueue.main.async(execute: { //Update UI self.tableView.reloadData() }) 

From AppCoda :

//This will print synchronously means, it will print 1-9 & 100-109 func simpleQueues() { let queue = DispatchQueue(label: "com.appcoda.myqueue") queue.sync { for i in 0..<10 { print("🔴", i) } } for i in 100..<110 { print("Ⓜ️", i) } } //This will print asynchronously func simpleQueues() { let queue = DispatchQueue(label: "com.appcoda.myqueue") queue.async { for i in 0..<10 { print("🔴", i) } } for i in 100..<110 { print("Ⓜ️", i) } } 
4

Swift 3 version

Swift 3 utilizes new DispatchQueue class to manage queues and threads. To run something on the background thread you would use:

let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background) backgroundQueue.async { print("Run on background thread") } 

Or if you want something in two lines of code:

DispatchQueue.global(qos: .background).async { print("Run on background thread") DispatchQueue.main.async { print("We finished that.") // only back on the main thread, may you access UI: label.text = "Done." } } 

You can also get some in-depth info about GDC in Swift 3 in this tutorial.

1

From Jameson Quave's tutorial

Swift 2

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //All stuff here }) 
5

Swift 4.x

Put this in some file:

func background(work: @escaping () -> ()) { DispatchQueue.global(qos: .userInitiated).async { work() } } func main(work: @escaping () -> ()) { DispatchQueue.main.async { work() } } 

and then call it where you need:

background { //background job main { //update UI (or what you need to do in main thread) } } 

Swift 5

To make it easy, create a file "DispatchQueue+Extensions.swift" with this content :

import Foundation typealias Dispatch = DispatchQueue extension Dispatch { static func background(_ task: @escaping () -> ()) { Dispatch.global(qos: .background).async { task() } } static func main(_ task: @escaping () -> ()) { Dispatch.main.async { task() } } } 

Usage :

Dispatch.background { // do stuff Dispatch.main { // update UI } } 

You have to separate out the changes that you want to run in the background from the updates you want to run on the UI:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { // do your task dispatch_async(dispatch_get_main_queue()) { // update some UI } } 
2

Since the OP question has already been answered above I just want to add some speed considerations:

I don't recommend running tasks with the .background thread priority especially on the iPhone X where the task seems to be allocated on the low power cores.

Here is some real data from a computationally intensive function that reads from an XML file (with buffering) and performs data interpolation:

Device name / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
  2. iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5s: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s

Note that the data set is not the same for all devices. It's the biggest on the iPhone X and the smallest on the iPhone 5s.

Good answers though, anyway I want to share my Object Oriented solution Up to date for swift 5.

please check it out: AsyncTask

Conceptually inspired by android's AsyncTask, I've wrote my own class in Swift

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread.

Here are few usage examples

Example 1 -

AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void print(p);//print the value in background thread }).execute("Hello async");//execute with value 'Hello async' 

Example 2 -

let task2=AsyncTask(beforeTask: { print("pre execution");//print 'pre execution' before backgroundTask },backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String if p>0{//check if execution value is bigger than zero return "positive"//pass String "poitive" to afterTask } return "negative";//otherwise pass String "negative" }, afterTask: {(p:String) in print(p);//print background task result }); task2.execute(1);//execute with value 1 

It has 2 generic types:

  • BGParam - the type of the parameter sent to the task upon execution.

  • BGResult - the type of the result of the background computation.

    When you create an AsyncTask you can those types to whatever you need to pass in and out of the background task, but if you don't need those types, you can mark it as unused with just setting it to: Void or with shorter syntax: ()

When an asynchronous task is executed, it goes through 3 steps:

  1. beforeTask:()->Void invoked on the UI thread just before the task is executed.
  2. backgroundTask: (param:BGParam)->BGResult invoked on the background thread immediately after
  3. afterTask:(param:BGResult)->Void invoked on the UI thread with result from the background task
1

Multi purpose function for thread

public enum QueueType { case Main case Background case LowPriority case HighPriority var queue: DispatchQueue { switch self { case .Main: return DispatchQueue.main case .Background: return DispatchQueue(label: "com.app.queue", qos: .background, target: nil) case .LowPriority: return DispatchQueue.global(qos: .userInitiated) case .HighPriority: return DispatchQueue.global(qos: .userInitiated) } } } func performOn(_ queueType: QueueType, closure: @escaping () -> Void) { queueType.queue.async(execute: closure) } 

Use it like :

performOn(.Background) { //Code } 
0

I really like Dan Beaulieu's answer, but it doesn't work with Swift 2.2 and I think we can avoid those nasty forced unwraps!

func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) { dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { background?() if let completion = completion{ let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(popTime, dispatch_get_main_queue()) { completion() } } } } 

Grand Central Dispatch is used to handle multitasking in our iOS apps.

You can use this code

// Using time interval DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) { print("Hello World") } // Background thread queue.sync { for i in 0..<10 { print("Hello", i) } } // Main thread for i in 20..<30 { print("Hello", i) } 

More information use this link :

Is there a drawback (when needing to launch a foreground screen afterward) to the code below?

import Foundation import UIKit class TestTimeDelay { static var connected:Bool = false static var counter:Int = 0 static func showAfterDelayControl(uiViewController:UIViewController) { NSLog("TestTimeDelay", "showAfterDelayControl") } static func tryReconnect() -> Bool { counter += 1 NSLog("TestTimeDelay", "Counter:\(counter)") return counter > 4 } static func waitOnConnectWithDelay(milliseconds:Int, uiViewController: UIViewController) { DispatchQueue.global(qos: .background).async { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(milliseconds), execute: { waitOnConnect(uiViewController: uiViewController) }) } } static func waitOnConnect(uiViewController:UIViewController) { connected = tryReconnect() if connected { showAfterDelayControl(uiViewController: uiViewController) } else { waitOnConnectWithDelay(milliseconds: 200, uiViewController:uiViewController) } } } 
1
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { // Conversion into base64 string self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn) }) 

in Swift 4.2 this works.

import Foundation class myThread: Thread { override func main() { while(true) { print("Running in the Thread"); Thread.sleep(forTimeInterval: 4); } } } let t = myThread(); t.start(); while(true) { print("Main Loop"); sleep(5); } 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy