在Swift中如何在GCD主线程上调用带参数的方法?

alm*_*mel 184 parameters grand-central-dispatch swift

在我的应用程序中,我有一个函数,它生成NSRURLSession并使用发送NSURLRequest

sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)
Run Code Online (Sandbox Code Playgroud)

在这个任务的完成块中,我需要做一些计算,将UIImage添加到调用viewcontroller.我有一个叫做的功能

func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
Run Code Online (Sandbox Code Playgroud)

这是UIImage添加计算.如果我尝试在完成块内运行视图添加代码,Xcode会抛出一个错误,说我在后台进程中无法使用布局引擎.所以我在SO上发现了一些试图在主线程上排队方法的代码:

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)
                        })
Run Code Online (Sandbox Code Playgroud)

但是,我不知道如何将参数"receiveAddr"和"amountBTC"添加到此函数调用中.我该怎么做,或者有人可以建议一种方法调用添加到应用程序主队列的最佳方法吗?

cod*_*ter 475

只需写下来.completion handler不需要使用dispatch_after

dispatch_async(dispatch_get_main_queue(), {
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
})
Run Code Online (Sandbox Code Playgroud)

迅捷3/4:

DispatchQueue.main.async { 
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
}
Run Code Online (Sandbox Code Playgroud)

也适用于主队列之后调度

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  // your code here
}
Run Code Online (Sandbox Code Playgroud)

替换YourAppDelegateClass为委托类


Daz*_*ong 80

Swift 3和Swift 4版本:

DispatchQueue.main.async {
    print("Hello")
}
Run Code Online (Sandbox Code Playgroud)

Swift3和XCode 9.2:

dispatch_async_on_main_queue {
     //Your code
     print("Hello")
 }
Run Code Online (Sandbox Code Playgroud)


Max*_*ler 15

斯威夫特2

使用尾随闭包这将成为:

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}
Run Code Online (Sandbox Code Playgroud)

尾随闭包是Swift语法糖,可以在函数参数范围之外定义闭包.有关更多信息,请参阅Swift 2.2编程语言指南中的尾随闭包.

在dispatch_async情况下,API是func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)因为dispatch_block_t是类型别名() -> Void-接收0参数和不具有一个返回值,并且块是所述函数的最后一个参数,我们可以在的外范围限定封闭的封闭件dispatch_async.


pej*_*alo 6

这里有更好的(IMO)Swifty/Cocoa样式语法来实现与其他答案相同的结果:

NSOperationQueue.mainQueue().addOperationWithBlock({
    // Your code here
})
Run Code Online (Sandbox Code Playgroud)

或者您可以获取流行的Async Swift库,以获得更少的代码和更多功能:

Async.main {
    // Your code here
}
Run Code Online (Sandbox Code Playgroud)


小智 6

在主线程上重新加载collectionView

 DispatchQueue.main.async {
      self.collectionView.reloadData()
 }
Run Code Online (Sandbox Code Playgroud)


Sai*_*yas 5

你可以使用切换到主线程

DispatchQueue.main.async {
        // UI Code Goes Here
    }
Run Code Online (Sandbox Code Playgroud)

您还可以编写更多可重用和可读的代码,我通过以下 POP 为您编写自定义协议

protocol MainThreadRunAble : AnyObject {}
Run Code Online (Sandbox Code Playgroud)

使用扩展实现协议

extension MainThreadRunAble {
func runOnMain(code : @escaping()->()) {
    DispatchQueue.main.async {
        code()
    }
}
func runOnMain(withDelay delay : Float ,code : @escaping()->()){
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
       code()
    }
}}
Run Code Online (Sandbox Code Playgroud)

使您的类符合您想要在主线程上运行的协议

class YourClass : BaseClass,MainThreadRunAble{}
Run Code Online (Sandbox Code Playgroud)

然后根据您的要求调用其中一种方法

runOnMain {
        //update on main
    }
    runOnMain(withDelay: 1) {
    //update on main
    }
Run Code Online (Sandbox Code Playgroud)

如果您使用任何架构并且只是想确保只有 viewcontroller 有权访问这段代码以在主线程上运行,然后实现您的扩展

extension UIViewController {
func runOnMain(code : @escaping()->()) {
    DispatchQueue.main.async {
        code()
    }
}
func runOnMain(withDelay delay : Float ,code : @escaping()->()){
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
       code()
    }
}}
Run Code Online (Sandbox Code Playgroud)