Как запрограммировать задержку (delay) в Swift 3?
Правильный способ: DispatchQueue.asyncAfter
В Swift 3 и последующих версиях Apple полностью переработала API Grand Central Dispatch (GCD). Старый C-подобный синтаксис dispatch_after заменён на более читаемый и безопасный метод DispatchQueue.asyncAfter. Вот как это работает:
Базовый пример задержки в 2 секунды
// Выполнить код на главном потоке через 2 секунды
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
// Ваш код здесь
print("Прошло 2 секунды!")
myLabel.isHidden = true
}
Разберём по частям:
- DispatchQueue.main — указывает, что код будет выполняться на главном потоке (UI-потоке). Это важно, если вы обновляете интерфейс (UILabel, UIButton и т.д.).
- .asyncAfter — метод, который планирует выполнение блока кода через указанное время.
- deadline: .now() + 2.0 — время, через которое код должен выполниться.
.now()— это текущий момент, а+ 2.0— добавляет 2 секунды.
Как сделать задержку на фоновом потоке?
Если вам не нужно обновлять UI, а нужно выполнить тяжёлую работу (например, загрузку данных), используйте глобальную очередь:
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 3.0) {
// Фоновая задача через 3 секунды
print("Это выполнится на фоновом потоке")
}
Более точная задержка с микросекундами
Если вам нужно указать время с высокой точностью, используйте DispatchTimeInterval:
let delayInSeconds = 1.5
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(Int(delayInSeconds))) {
// Через 1.5 секунды
}
// Или напрямую с миллисекундами:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1500)) {
// Тот же эффект
}
Отмена запланированной задержки
Иногда нужно отменить задержку до её выполнения (например, если пользователь нажал кнопку повторно). Для этого сохраните DispatchWorkItem:
// Создаём задачу
let workItem = DispatchWorkItem {
print("Эта задача будет выполнена через 5 секунд, если не отменена")
}
// Планируем
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0, execute: workItem)
// Отменяем (если нужно)
workItem.cancel()
Почему старый код не работает?
В Swift 3 Apple убрала все C-функции GCD. Вместо dispatch_after теперь используется объектно-ориентированный подход через DispatchQueue. Это делает код более безопасным и читаемым. Всегда используйте DispatchQueue.main.asyncAfter для UI-операций и DispatchQueue.global().asyncAfter для фоновых задач.
Теперь вы можете смело вставлять этот код в свой проект. Удачи!
<<Альтернативный подход: Timer (NSTimer)
Если вам нужно выполнить действие только один раз с задержкой, можно использовать Timer. Этот метод особенно удобен, когда задержка связана с повторяющимися событиями или есть вероятность отмены:
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { timer in
// Код выполнится через 2 секунды
self.myLabel.isHidden = true
}
Преимущества Timer:
- Легко отменить: сохраните ссылку на таймер и вызовите
timer.invalidate(). - Поддерживает повторение (
repeats: true), что полезно для периодических задач. - Не требует указания очереди — по умолчанию выполняется на главном потоке.
Недостаток: таймер чувствителен к циклу выполнения (RunLoop). Если главный поток занят, задержка может увеличиться. Для точных задержек лучше использовать asyncAfter.
Пример с отменой:
var myTimer: Timer?
func startDelay() {
myTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { _ in
print("Выполнено")
}
}
func cancelDelay() {
myTimer?.invalidate()
myTimer = nil
}
Выбирайте asyncAfter для простых одноразовых задержек и Timer — когда нужна гибкость управления.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги