В Swift как вызвать метод с параметрами в основной теме GCD?

В моем приложении у меня есть функция, которая делает NSRURLSession и отправляет NSURLRequest, используя

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

В блоке завершения для этой задачи мне нужно сделать некоторые вычисления, которые добавят UIImage к вызывающему диспетчеру просмотра. У меня есть функция, называемая

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". Как я могу это сделать, или кто-то может предложить оптимальный способ добавления вызова метода в основную очередь приложения?

Ответ 1

Просто напишите это в completion handler нужно использовать dispatch_after

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

Свифт 3:

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

Также для отправки после основной очереди

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

Замените YourAppDelegateClass вашим классом делегата.

Ответ 2

Версия Swift 3 & Swift 4:

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

Swift3 и XCode 9.2:

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

Ответ 3

Swift 2

Использование Trailing Closures становится следующим:

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

Trailing Closures - это синтаксический сахар Swift, который позволяет определять замыкание вне области параметров функции. Для получения дополнительной информации см. Trailing Closures в руководстве по языку программирования Swift 2.2.

В случае dispatch_async API func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t), поскольку dispatch_block_t является псевдонимом типа для () -> Void - закрытие, которое принимает 0 параметров и не имеет возвращаемого значения, а блок является последним параметром функции, которую мы можем определить замыкание во внешнем объеме dispatch_async.

Ответ 4

Здесь лучше (IMO) Swifty/ Cocoa синтаксис стиля для достижения того же результата, что и другие ответы:

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

Или вы могли бы захватить популярную библиотеку Async Swift за еще меньше кода и больше функциональности:

Async.main {
    // Your code here
}

Ответ 5

Правильный способ сделать это - использовать dispatch_async в main_queue, как я сделал в следующем коде

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

Ответ 6

Вот небольшая глобальная функция, которую вы можете добавить для лучшего синтаксиса:

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

И использование

dispatch_on_main {
    // Do some UI stuff
}

Ответ 7

Не забывайте ослаблять себя, если вы используете себя внутри закрытия.

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

Ответ 8

Перезагрузить коллекциюПосмотреть на главной теме

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

Ответ 9

//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()
})