Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое CADisplayLink?
CADisplayLink — это механизм в iOS и macOS, который позволяет синхронизировать выполнение кода с частотой обновления дисплея устройства (частота кадров). По сути, это таймер, привязанный к отрисовке кадров на экране, что делает его идеальным инструментом для плавной анимации, рендеринга в реальном времени (например, в играх или графических приложениях) и задач, требующих синхронизации с дисплеем.
Как работает CADisplayLink
В отличие от стандартных таймеров, таких как Timer (ранее NSTimer), который срабатывает на основе временных интервалов (например, каждые 0.016 секунд для 60 FPS), CADisplayLink напрямую связан с Vsync (вертикальная синхронизация) дисплея. Он вызывает заданный метод (селектор) каждый раз, когда система готовится к отрисовке нового кадра. Это обеспечивает:
- Высокую точность: Вызовы происходят в момент, оптимальный для обновления интерфейса.
- Энергоэффективность: Код выполняется только тогда, когда это действительно нужно для отрисовки, снижая нагрузку на CPU/GPU.
- Избегание "разрывов" кадров: Синхронизация с дисплеем минимизирует артефакты в анимации.
Ключевые свойства и методы
CADisplayLink предоставляет несколько важных свойств для контроля:
timestamp: Время последнего отрисованного кадра (в секундах).duration: Продолжительность между кадрами (например, ~0.016667 с для 60 Гц).preferredFramesPerSecond: Позволяет задать желаемую частоту кадров (например, 30, 60, 120 FPS), хотя реальная частота зависит от возможностей дисплея.isPaused: Флаг для приостановки/возобновления вызовов.add(to:forMode:)иinvalidate(): Методы для запуска и остановки связи с дисплеем.
Пример использования
Вот простой пример создания CADisplayLink для анимации перемещения объекта на экране (например, в игровом цикле):
import UIKit
class AnimationViewController: UIViewController {
private var displayLink: CADisplayLink?
private var startTime: CFTimeInterval = 0
private let animationDuration: CFTimeInterval = 2.0 // Длительность анимации в секундах
@IBOutlet weak var movingView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
setupDisplayLink()
}
private func setupDisplayLink() {
// Создаем CADisplayLink с целевым методом
displayLink = CADisplayLink(target: self, selector: #selector(updateAnimation))
// Устанавливаем желаемую частоту кадров (например, 60 FPS)
displayLink?.preferredFramesPerSecond = 60
// Добавляем в основной RunLoop в режиме .common
displayLink?.add(to: .main, forMode: .common)
startTime = CACurrentMediaTime()
}
@objc private func updateAnimation() {
let elapsed = CACurrentMediaTime() - startTime
if elapsed >= animationDuration {
// Завершаем анимацию
displayLink?.invalidate()
displayLink = nil
return
}
// Вычисляем прогресс анимации (от 0 до 1)
let progress = elapsed / animationDuration
// Обновляем позицию view (например, перемещаем по горизонтали)
let screenWidth = view.bounds.width
movingView.frame.origin.x = CGFloat(progress) * screenWidth
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Важно: останавливаем CADisplayLink при уходе с экрана
displayLink?.invalidate()
}
}
Сравнение с другими подходами
- CADisplayLink vs Timer:
Timerменее точен для анимации, так как зависит от RunLoop и может "дрейфовать" при высокой нагрузке системы.CADisplayLinkгарантирует вызовы в момент отрисовки кадра. - CADisplayLink vs Core Animation: Для стандартных UI-анимаций (например, перемещение, масштабирование) лучше использовать встроенные анимации Core Animation (например,
UIView.animate), так как они аппаратно ускорены.CADisplayLinkполезен для кастомной логики, где нужно контролировать каждый кадр. - CADisplayLink vs Metal/SceneKit: В современных графических фреймворках (Metal, SceneKit) часто используется собственный цикл рендеринга, но
CADisplayLinkможет служить для синхронизации неграфических задач (например, обновления физики в игре).
Плюсы и минусы
Плюсы:
- Высокая точность синхронизации с дисплеем.
- Эффективность для ресурсоемких задач (например, игры).
- Гибкость в управлении частотой кадров.
Минусы:
- Более сложный в использовании, чем стандартные анимации.
- Требует ручного управления жизненным циклом (запуск/остановка).
- Может создавать нагрузку на батарею, если используется без оптимизации.
Практические советы
- Всегда останавливайте
CADisplayLinkпри уходе с экрана (вviewWillDisappearилиdeinit), чтобы избежать утечек памяти. - Используйте режим
.commonв RunLoop для плавной работы во время пользовательского взаимодействия (например, скроллинга). - Оптимизируйте код в методе обновления: избегайте тяжелых операций, чтобы не пропускать кадры.
- Учитывайте частоту дисплея: на устройствах с ProMotion (до 120 Гц) можно установить
preferredFramesPerSecondдля баланса между плавностью и производительностью.
В итоге, CADisplayLink — это мощный низкоуровневый инструмент для синхронизации кода с дисплеем, который незаменим в задачах, где важна максимальная плавность и контроль над анимацией, но требует аккуратного использования.