Как запрограммировать задержку в 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?

Ответы:


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.

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


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
}

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
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.