Как мне написать dispatch_after GCD в Swift 3 и 4?

301

В Swift 2 я смог использовать dispatch_after для задержки действия с помощью центральной центральной отправки:

var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))) 
dispatch_after(dispatchTime, dispatch_get_main_queue(), { 
    // your function here 
})

Но это больше не похоже на компиляцию в Swift 3 (или 4). Каков предпочтительный способ записать это в Swift 3 (с использованием нового API-интерфейса Dispatch)?

  • 6
    Дополнительную информацию о процессе миграции можно найти здесь: https://swift.org/migration-guide/. Для этого вопроса важен раздел «Отправка».
  • 0
    Ваш вопрос должен быть UInt64 ?
Теги:
grand-central-dispatch
xcode8
swift3

10 ответов

671
Лучший ответ

Синтаксис просто:

// to run something in 0.1 seconds

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

Обратите внимание: вышеприведенный синтаксис добавления seconds как Double кажется источником путаницы (esp, так как мы привыкли добавлять nsec). Синтаксис "добавить секунды как Double" работает, потому что deadline является DispatchTime, а за кулисами существует оператор +, который примет Double и добавит, что много секунд до DispatchTime

public func +(time: DispatchTime, seconds: Double) -> DispatchTime

Но если вы действительно хотите добавить целое число msec, μs или nsec в DispatchTime, вы также можете добавить DispatchTimeInterval в DispatchTime. Это означает, что вы можете сделать:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
    os_log("500 msec seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
    os_log("1m μs seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
    os_log("1.5b nsec seconds later")
}

Все эти функции легко работают из-за этого отдельного метода перегрузки для оператора + в классе DispatchTime.

public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
  • 4
    Спасибо за то, что указал на это, и на самом деле swift.org/migration-guide упоминает о необходимости внести это изменение вручную.
  • 1
    Ой, извини. Здесь уже слишком поздно :). Мысль, что все беспорядок должен идти на самом деле, но не сделал прыжок. ИМО «простое» решение - это «одно истинное решение».
Показать ещё 5 комментариев
68

Swift 4:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
   // Code
}

В течение времени .seconds(Int) также могут использоваться .microseconds(Int) и .nanoseconds(Int).

  • 0
    @brandonscript Это более чистый код
  • 7
    .milliseconds лучше, чем Double.
Показать ещё 3 комментария
32

Если вам нужна функция задержки в

Swift 4

func delay(delay: Double, closure: @escaping () -> ()) {

     DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
          closure()
     }
}

Вы можете использовать его как:

delay(delay: 1) { 
    print("Hi!")
}
  • 0
    DispatchQueue.main.asyncAfter (deadline:) не работает. Он говорит, что не перегружает никакой метод из своего суперкласса.
  • 0
    Используете ли вы ту же версию XCode, как указано?
Показать ещё 1 комментарий
14

после выпуска Swift 3, также необходимо добавить @escaping

func delay(_ delay: Double, closure: @escaping () -> ()) {
  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
    closure()
  }
}
4

вызов DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)

Я настоятельно рекомендую использовать инструменты Xcode для преобразования в Swift 3 (Edit > Convert > To Current Swift Syntax). Это поймало это для меня.

0

попробуйте это

let when = DispatchTime.now() + 1.5
    DispatchQueue.main.asyncAfter(deadline: when) {
        //some code
    }
  • 0
    Не уверен, как это отличается от затронутого ответа?
0

Несколько иной аромат принятого ответа.

Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) + 
.microseconds(500) + .nanoseconds(1000)) {
                print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds + 
                      1000 nanoseconds)")
 }
0

Вы можете использовать

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
        // Code
    }
0

Вы можете создать функцию performAfter, которая использует Swift 3 DispatchAfter функцию внутри

func performAfter(delay: TimeInterval, completion: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        completion()
    }
}

и используйте

performAfter(delay: 2) {
   print("task to be done")
}
  • 2
    Чем это отличается от ответа @ rockdaswift?
  • 0
    как я уже упоминал, он оборачивает asyncAfter внутри функции executeAfter, которая принимает задержку в качестве параметра, и ее проще вызвать, используя просто executeAfter (delay: 2) {}
Показать ещё 2 комментария
0

Это работало для меня в 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)")
}
  • 4
    Не уверены, чем это отличается от принятого ответа?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню