Как запрограммировать задержку в Swift 3

330

В более ранних версиях Swift можно было создать задержку с помощью следующего кода:

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
    //put your code which should be executed with a delay here
}

Но теперь, в Swift 3, Xcode автоматически меняет 6 разных вещей, но затем появляется следующая ошибка: «Не удается преобразовать DispatchTime.nowв ожидаемое значение, dispatch_time_tиначе UInt64».

Как создать задержку перед запуском последовательности кода в Swift 3?

owlswipe
источник

Ответы:

967

После долгих исследований я наконец понял это.

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.
   // Code you want to be delayed
}

Это создает желаемый эффект ожидания в Swift 3 и Swift 4.

Вдохновлен частью этого ответа .

owlswipe
источник
7
Полезный вклад, спасибо! Обновление для последней версии Swift 3:DispatchQueue.main.asyncAfter(deadline: when)
Rogare
77
Вы можете сделать свой код немного более быстрым, заменив «+ 2» на «+ .seconds (2)». Или, для максимальной гибкости, вы можете опустить первую строку и заменить «дедлайн: когда» на «дедлайн: .now () + .seconds (2)».
RenniePet
2
@ OctavioAntonioCedeño Рад помочь.
Некоторое
5
Все еще работает 12.03.2017. Большое спасибо за это :)
Джон Леонардо
3
Буквально мой самый посещаемый пост на SO. Легче найти этот пост, чем запомнить его или найти в другом месте в моем коде;)
barrylachapelle
154

Мне нравится однострочная нотация для GCD, она более элегантна:

    DispatchQueue.main.asyncAfter(deadline: .now() + 42.0) {
        // do stuff 42 seconds later
    }

Также в iOS 10 появились новые методы Timer, например, инициализатор блока:

(поэтому отложенное действие может быть отменено)

    let timer = Timer.scheduledTimer(withTimeInterval: 42.0, repeats: false) { (timer) in
        // do stuff 42 seconds later
    }

Кстати, имейте в виду: по умолчанию таймер добавляется в режим цикла выполнения по умолчанию. Это означает, что таймер может быть заморожен, когда пользователь взаимодействует с пользовательским интерфейсом вашего приложения (например, при прокрутке UIScrollView). Вы можете решить эту проблему, добавив таймер в определенный режим цикла выполнения:

RunLoop.current.add(timer, forMode: .common)

В этом блоге вы можете найти более подробную информацию.

Виктор До
источник
4
Хороший улов! Я еще этого не видел.
julien_c
8
плюс один за сравнение таймера и отказ от ответственности о главном цикле выполнения!
Мартин
2
Хорошо поймал! Это инженерия.
Онур Шахиндур
56

Попробуйте следующую функцию, реализованную в Swift 3.0 и выше

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

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

delayWithSeconds(1) {
   //Do something
}
Vakas
источник
5
Вы просто скопировали этот ответ, но да, это хорошо, спасибо.
owlswipe
2
Как отменить это?
Сурав Чандра
24

Попробуйте приведенный ниже код для задержки

//MARK: First Way

func delayForWork() {
    delay(3.0) {
        print("delay for 3.0 second")
    }
}

delayForWork()

// MARK: Second Way

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    // your code here delayed by 0.5 seconds
}
Ананд Верма
источник
1
Дисплеи с первым способом имеют ошибку «Использование неразрешенного идентификатора« задержка »»
Джерри Чонг,
5
Этот программист работает с вспомогательным методом в своей базе кода и имеет в течение длительного времени. Таким образом, задержка была кодом, который он использовал некоторое время, не зная, что он не является частью Apple SDK.
Ник Перкинс
4

Одним из способов является использование, DispatchQueue.main.asyncAfterкак многие люди ответили.

Другой способ заключается в использовании perform(_:with:afterDelay:). Подробнее здесь

perform(#selector(delayedFunc), with: nil, afterDelay: 3)

@IBAction func delayedFunc() {
    // implement code
}
Зохайб Брохи
источник
1

// Запускает функцию через х секунд

public static func runThisAfterDelay(seconds: Double, after: @escaping () -> Void) {
    runThisAfterDelay(seconds: seconds, queue: DispatchQueue.main, after: after)
}

public static func runThisAfterDelay(seconds: Double, queue: DispatchQueue, after: @escaping () -> Void) {
    let time = DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
    queue.asyncAfter(deadline: time, execute: after)
}

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

runThisAfterDelay(seconds: x){
  //write your code here
}
Пратюш Пратик
источник