В моем приложении у меня есть функция, которая делает 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". Как я могу это сделать, или кто-то может предложить оптимальный способ добавления вызова метода в основную очередь приложения?
Просто напишите это в 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
вашим классом делегата.
Версия Swift 3 & Swift 4:
DispatchQueue.main.async {
print("Hello")
}
Swift3 и XCode 9.2:
dispatch_async_on_main_queue {
//Your code
print("Hello")
}
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
.
Здесь лучше (IMO) Swifty/ Cocoa синтаксис стиля для достижения того же результата, что и другие ответы:
NSOperationQueue.mainQueue().addOperationWithBlock({
// Your code here
})
Или вы могли бы захватить популярную библиотеку Async Swift за еще меньше кода и больше функциональности:
Async.main {
// Your code here
}
Правильный способ сделать это - использовать dispatch_async в main_queue, как я сделал в следующем коде
dispatch_async(dispatch_get_main_queue(), {
(self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
})
Вот небольшая глобальная функция, которую вы можете добавить для лучшего синтаксиса:
func dispatch_on_main(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
И использование
dispatch_on_main {
// Do some UI stuff
}
Не забывайте ослаблять себя, если вы используете себя внутри закрытия.
dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in
if let strongSelf = self {
self?.doSomething()
}
})
//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()
})
Перезагрузить коллекциюПосмотреть на главной теме
DispatchQueue.main.async {
self.collectionView.reloadData()
}
addUIImage
addUIImage. Если это в делегатеapp delegate
чем он будет работать. Я проверил это работает правильно