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

时间:2014-07-27 21:12:48

标签: parameters swift grand-central-dispatch

在我的应用程序中,我有一个函数可以创建NSRURLSession并使用

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

在此任务的完成块中,我需要进行一些计算,将UIImage添加到调用viewcontroller。我有一个叫做

的功能
func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)

执行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)
                        })

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

9 个答案:

答案 0 :(得分:441)

只需在completion handler中写一下。无需使用dispatch_after

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

Swift 3/4:

DispatchQueue.main.async { 
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
}

也适用于在主队列之后发送

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

YourAppDelegateClass替换为委派类

答案 1 :(得分:74)

斯威夫特3& Swift 4版本:

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

Swift3和XCode 9.2:

dispatch_async_on_main_queue {
     //Your code
     print("Hello")
 }

答案 2 :(得分:14)

Swift 2

使用尾随闭包这将成为:

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

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

在dispatch_async情况下,API为func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t),因为dispatch_block_t() -> Void的类型别名 - 一个闭包,它接收0个参数但没有返回值,并且阻塞是最后一个参数我们可以在dispatch_async的外部范围内定义闭包的函数。

答案 3 :(得分:6)

这是更好的(IMO)Swifty / Cocoa风格语法,可以获得与其他答案相同的结果:

normal.c

或者你可以获得更受欢迎的Async Swift library以获得更少的代码和更多功能:

void clear_showcmd(void)

答案 4 :(得分:5)

在主线程上重新加载collectionView

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

答案 5 :(得分:3)

执行此操作的正确方法是在main_queue中使用dispatch_async,就像我在以下代码中所做的那样

dispatch_async(dispatch_get_main_queue(), {
                        (self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
                        })

答案 6 :(得分:2)

这是一个很好的小全局函数,你可以为更好的语法添加:

func dispatch_on_main(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

使用

dispatch_on_main {
    // Do some UI stuff
}

答案 7 :(得分:1)

如果你在封闭内部使用自我,不要忘记削弱自我。

dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in
            if let strongSelf = self {
                self?.doSomething()
            }
        })

答案 8 :(得分:1)

//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {  
    // Call your function here
    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()
})