In Swift how to call method with parameters on GCD main thread?

183,930

Solution 1

Modern versions of Swift use DispatchQueue.main.async to dispatch to the main thread:

DispatchQueue.main.async { 
  // your code here
}

To dispatch after on the main queue, use:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  // your code here
}

Older versions of Swift used:

dispatch_async(dispatch_get_main_queue(), {
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
})

Solution 2

Swift 3+ & Swift 4 version:

DispatchQueue.main.async {
    print("Hello")
}

Swift 3 and Xcode 9.2:

dispatch_async_on_main_queue {
    print("Hello")
}

Solution 3

Swift 2

Using Trailing Closures this becomes:

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

Trailing Closures is Swift syntactic sugar that enables defining the closure outside of the function parameter scope. For more information see Trailing Closures in Swift 2.2 Programming Language Guide.

In dispatch_async case the API is func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t) since dispatch_block_t is type alias for () -> Void - A closure that receives 0 parameters and does not have a return value, and block being the last parameter of the function we can define the closure in the outer scope of dispatch_async.

Solution 4

Reload collectionView on Main Thread

DispatchQueue.main.async {
    self.collectionView.reloadData()
}

Solution 5

Here's the nicer (IMO) Swifty/Cocoa style syntax to achieve the same result as the other answers:

NSOperationQueue.mainQueue().addOperationWithBlock({
    // Your code here
})

Or you could grab the popular Async Swift library for even less code and more functionality:

Async.main {
    // Your code here
}
Share:
183,930

Related videos on Youtube

almel
Author by

almel

Bitcoin enthusiast working to promote Bitcoin 2.0. PM me for any work involving help developing bitcoin technologies.

Updated on July 22, 2022

Comments

  • almel
    almel almost 2 years

    In my app I have a function that makes an NSRURLSession and sends out an NSURLRequest using

    sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)
    

    In the completion block for this task, I need to do some computation that adds a UIImage to the calling viewcontroller. I have a func called

    func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
    

    that does the UIImage-adding computation. If I try to run the view-adding code inside of the completion block, Xcode throws an error saying that I can't use the layout engine while in a background process. So I found some code on SO that tries to queue a method on the main thread:

    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))
    
    dispatch_after(time, dispatch_get_main_queue(), {
        let returned = UIApplication.sharedApplication().sendAction("displayQRCode:", to: self.delegate, from: self, forEvent: nil)
    })
    

    However, I don't know how to add the parameters "receiveAddr" and "amountBTC" to this function call. How would I do this, or can someone suggest an optimal way for adding a method call to the application's main queue?

  • almel
    almel almost 10 years
    While you are correct that your suggestion works, I think my answer is slightly better because it does not make a call to UIApplication.sharedApplication, which is unusual and might throw off other readers of my code. The scope of my answer is constrained to the objects of importance, while yours brings in ancillary objects that require me to read more docs to learn exactly what I'm doing. And I've edited my original question to contain the correct function call. I had thought the displayQRCode wasn't specific enough but with our comments now it is. Thanks for pointing that out.
  • Laszlo
    Laszlo about 8 years
    that was exactly the 3 lines i'm looking for ... now you can stop reading my mind
  • Jackspicer
    Jackspicer over 7 years
    Could you please explain why we should be doing this ?
  • jackofallcode
    jackofallcode about 7 years
    It's because it can create memory cycles - i.e. I have a strong reference to something and it has a strong reference to me. Meaning neither of us can leave the memory heap.
  • Frostmourne
    Frostmourne about 4 years
    method renamed to OperationQueue.main.addOperation({ }