dispatch_after – GCD в быстром?

Я прошел через iBook от Apple и не смог найти никакого определения:

Может кто-нибудь объяснить структуру dispatch_after ?

 dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>) 

14 Solutions collect form web for “dispatch_after – GCD в быстром?”

Более четкое представление о структуре:

 dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?) 

dispatch_time_tUInt64 . dispatch_queue_t на самом деле является псевдонимом NSObject , но вы должны просто использовать свои привычные методы GCD для получения очередей. Блок – это быстрое закрытие. В частности, dispatch_block_t определяется как () -> Void , что эквивалентно () -> () .

Пример использования:

 let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))) dispatch_after(delayTime, dispatch_get_main_queue()) { print("test") } 

РЕДАКТИРОВАТЬ:

Я рекомендую использовать очень хорошую функцию delay @ matt .

EDIT 2:

В Swift 3 появятся новые обертки для GCD. См. Здесь: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md

Исходный пример будет написан следующим образом в Swift 3:

 let deadlineTime = DispatchTime.now() + .seconds(1) DispatchQueue.main.asyncAfter(deadline: deadlineTime) { print("test") } 

Обратите внимание, что вы можете записать объявление deadlineTime как DispatchTime.now() + 1.0 и получить тот же результат, потому что оператор + переопределяется следующим образом (аналогично для - ):

  • func +(time: DispatchTime, seconds: Double) -> DispatchTime
  • func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime

Это означает, что если вы не используете enum DispatchTimeInterval и просто записываете номер, предполагается, что вы используете секунды.

Я использую dispatch_after так часто, что написал функцию утилиты верхнего уровня, чтобы упростить синтаксис:

 func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) } 

И теперь вы можете говорить так:

 delay(0.4) { // do stuff } 

Вау, язык, на котором вы можете улучшить язык. Что может быть лучше?


Обновление для Swift 3, Xcode 8 Seed 6

Кажется, почти не стоит беспокоиться, теперь, когда они улучшили синтаксис вызова:

 func delay(_ delay:Double, closure:@escaping ()->()) { let when = DispatchTime.now() + delay DispatchQueue.main.asyncAfter(deadline: when, execute: closure) } 

Матовый синтаксис очень хорош, и если вам нужно сделать недействительным блок, вы можете использовать это:

 typealias dispatch_cancelable_closure = (cancel : Bool) -> Void func delay(time:NSTimeInterval, closure:()->Void) -> dispatch_cancelable_closure? { func dispatch_later(clsr:()->Void) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), clsr) } var closure:dispatch_block_t? = closure var cancelableClosure:dispatch_cancelable_closure? let delayedClosure:dispatch_cancelable_closure = { cancel in if closure != nil { if (cancel == false) { dispatch_async(dispatch_get_main_queue(), closure!); } } closure = nil cancelableClosure = nil } cancelableClosure = delayedClosure dispatch_later { if let delayedClosure = cancelableClosure { delayedClosure(cancel: false) } } return cancelableClosure; } func cancel_delay(closure:dispatch_cancelable_closure?) { if closure != nil { closure!(cancel: true) } } 

Использовать следующим образом

 let retVal = delay(2.0) { println("Later") } delay(1.0) { cancel_delay(retVal) } 

кредиты

Ссылка выше, похоже, не работает. Оригинальный код Objc от Github

Чтобы расширить ответ Кезари, который будет выполняться через 1 наносекунду, я должен был выполнить следующие действия через 4 с половиной секунды.

  let delay = 4.5 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), block) 

Edit: Я обнаружил, что мой оригинальный код был немного неправильным. Неявная типизация вызывает ошибку компиляции, если вы не передали NSEC_PER_SEC в Double.

Если кто-то может предложить более оптимальное решение, я бы хотел его услышать.

== Обновление для Swift 3 ==

Это супер-легко и элегантно в Swift 3:

  DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) { // ... } 

У Apple есть фрагмент dispatch_after для Objective-C :

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ <#code to be executed after a specified delay#> }); 

Вот тот же фрагмент, портированный на Swift 3:

 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + <#delayInSeconds#>) { <#code to be executed after a specified delay#> } 

Другим способом является расширение Double следующим образом:

 extension Double { var dispatchTime: dispatch_time_t { get { return dispatch_time(DISPATCH_TIME_NOW,Int64(self * Double(NSEC_PER_SEC))) } } } 

Затем вы можете использовать его следующим образом:

 dispatch_after(Double(2.0).dispatchTime, dispatch_get_main_queue(), { () -> Void in self.dismissViewControllerAnimated(true, completion: nil) }) 

Мне нравится функция задержки мата, но только из-за предпочтения я бы предпочел ограничить прохождение закрытий.

Самое простое решение в Swift 3.0 и Swift 4.0

 func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) { DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { completion() } } 

Применение

 delayWithSeconds(1) { //Do something } 

В Swift 3.0

Очереди отправки

  DispatchQueue(label: "test").async { //long running Background Task for obj in 0...1000 { print("async \(obj)") } // UI update in main queue DispatchQueue.main.async(execute: { print("UI update on main queue") }) } DispatchQueue(label: "m").sync { //long running Background Task for obj in 0...1000 { print("sync \(obj)") } // UI update in main queue DispatchQueue.main.sync(execute: { print("UI update on main queue") }) } 

Отправка через 5 секунд

  DispatchQueue.main.after(when: DispatchTime.now() + 5) { print("Dispatch after 5 sec") } 

1) Добавьте этот метод как часть расширения UIViewController.

 extension UIViewController{ func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) { let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) dispatch_after(time, dispatch_get_main_queue(), block) } } 

Вызовите этот метод на VC:

  self.runAfterDelay(5.0, block: { //Add code to this block print("run After Delay Success") }) 

2) выполнитьSelector ("yourMethod Name", withObject: nil, afterDelay: 1)

3)

 override func viewWillAppear(animated: Bool) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue(), { () -> () in //Code Here }) 

// Компактная форма

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue()) { //Code here } 

}

Хотя не оригинальный вопрос OP, некоторые NSTimer связанные с NSTimer , были отмечены как дубликаты этого вопроса, поэтому стоит NSTimer ответ NSTimer .

NSTimer vs dispatch_after

  • NSTimer более высокий уровень, а dispatch_after – более низкий уровень.
  • NSTimer легче отменить. Отмена dispatch_after требует написания большего количества кода .

Задержка задачи с помощью NSTimer

Создайте экземпляр NSTimer .

 var timer = NSTimer() 

Запустите таймер с необходимой задержкой.

 // invalidate the timer if there is any chance that it could have been called before timer.invalidate() // delay of 2 seconds timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) 

Добавьте функцию, которая будет вызываться после задержки (используя любое имя, которое вы использовали для параметра selector выше).

 func delayedAction() { print("Delayed action has now started." } 

Заметки

  • Если вам нужно отменить действие до его timer.invalidate() , просто вызовите timer.invalidate() .
  • Для повторного использования действия repeats: true .
  • Если у вас есть одноразовый случай без необходимости отмены, нет необходимости создавать переменную экземпляра timer . Для этого достаточно:

     NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) 
  • См. Мой более полный ответ здесь .

Версия Swift 3.0

После закрытия функция выполняет некоторую задачу после задержки на основном потоке.

 func performAfterDelay(delay : Double, onCompletion: @escaping() -> Void){ DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: { onCompletion() }) } 

Вызовите эту функцию следующим образом:

 performAfterDelay(delay: 4.0) { print("test") } 

Другой помощник, чтобы задержать ваш код, который является 100% Swift в использовании и, возможно, позволяет выбрать другой поток для запуска вашего отложенного кода:

 public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) { let dispatchTime = DispatchTime.now() + seconds dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure) } public enum DispatchLevel { case main, userInteractive, userInitiated, utility, background var dispatchQueue: DispatchQueue { switch self { case .main: return DispatchQueue.main case .userInteractive: return DispatchQueue.global(qos: .userInteractive) case .userInitiated: return DispatchQueue.global(qos: .userInitiated) case .utility: return DispatchQueue.global(qos: .utility) case .background: return DispatchQueue.global(qos: .background) } } } 

Теперь вы просто задерживаете свой код в основном потоке следующим образом:

 delay(bySeconds: 1.5) { // delayed code } 

Если вы хотите отложить свой код на другой поток :

 delay(bySeconds: 1.5, dispatchLevel: .background) { // delayed code that will run on background thread } 

Если вы предпочитаете Framework, который также имеет некоторые более удобные функции, то проверьте HandySwift . Вы можете добавить его в свой проект через Carthage, а затем использовать его точно так же, как в приведенных выше примерах, например:

 import HandySwift delay(bySeconds: 1.5) { // delayed code } 

Это сработало для меня.

Swift 3:

 let time1 = 8.23 let time2 = 3.42 // Delay 2 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("Sum of times: \(time1 + time2)") } 

Objective-C:

 CGFloat time1 = 3.49; CGFloat time2 = 8.13; // Delay 2 seconds dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ CGFloat newTime = time1 + time2; NSLog(@"New time: %f", newTime); }); 

используйте этот код для выполнения некоторой задачи, связанной с пользовательским интерфейсом, через 2.0 секунды.

  let delay = 2.0 let delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) let mainQueue = dispatch_get_main_queue() dispatch_after(delayInNanoSeconds, mainQueue, { print("Some UI related task after delay") }) 

Версия Swift 3.0

После закрытия функция выполняет некоторую задачу после задержки на основном потоке.

 func performAfterDelay(delay : Double, onCompletion: @escaping() -> Void){ DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: { onCompletion() }) } 

Вызовите эту функцию следующим образом:

 performAfterDelay(delay: 4.0) { print("test") } 
  • AVSpeechSynthesizer не работает на iOS10
  • Почему тип персонажа Swift не Hashable?
  • UITapGestureRecognizer & UIDataDetectorTypes работает одновременно
  • Swift 3 | Обновление Xcode 8 datePicker UItextField
  • Каким будет поток для подключения двух периферийных устройств BLE?
  • UITableView.visibleCells не захватывает все видимые ячейки
  • Автоматическое отключение программ не работает
  • Выполнять запрос POST в Swift
  • Как фильтровать словарь и выводить результат в CollectionViewController в swift
  • Обрезка SKTexture с текстом SKLabel
  • Как выполнить аутентификацию пользователя в SDK для Parse iOS с помощью OAuth?
  • Interesting Posts

    Быстрая навигационная панель Заголовок изображения

    Заголовок в раскадровке для UITableViewController не "прилипает"

    Xcode и iOS5.1 на iPhone не будут работать

    Фон показывает, когда появляется UIImagePickerController

    Проблема с API VPImageCropperViewController

    Восстановительные веб-сервисы для мобильных приложений – Какой язык, инфраструктура, инфраструктура?

    Предикат даты не работает

    Невозможно редактировать видео с помощью GPUImage

    управление и упаковка зависимостей iOS

    Использовать самоподписанный сертификат ssl в приложении iphone

    Получить конкретное значение между функцией Javascript с помощью NSRegularExpression?

    – : непризнанный селектор, отправленный в экземпляр 0x776e920 '

    Премиальные способы оплаты SMS и IVR в приложениях iOS

    Предупреждение. Попробуйте представить <UIAlertController: 0x7facd3946920> в <…>, который уже представляет (null)

    Доступ к музыкальным файлам устройства устройства из приложения iPhone программно

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.