UIKit Dynamics — фреймворк физической анимации в iOS (UIKit), позволяющий View взаимодействовать по законам реальной физики: гравитация, столкновения, упругость и силы притяжения. Статья объясняет компоненты UIDynamicAnimator, виды поведений (behavior) и практические сценарии применения.
Главное
UIKit Dynamics — фреймворк физического моделирования, представленный Apple в iOS 7 (2013). В отличие от UIView.animate (линейные переходы) и Core Animation (анимация слоёв), UIKit Dynamics моделирует реальные физические взаимодействия: гравитацию, столкновения, силы, упругость и трение. Разработчик добавляет поведения (behaviors) к UIDynamicAnimator, и система автоматически рассчитывает физику для каждого кадра.
Фреймворк работает на частоте 60/120 FPS и использует встроенный физический движок на основе симуляции твёрдых тел (rigid body simulation). UIKit Dynamics не требует знания физики или математики — достаточно применить готовое поведение и настроить параметры.
По данным Apple, UIKit Dynamics подходит для UI-эффектов (анимация стопки карт, «дрожание» иконок, физика интерфейса), но не предназначен для игр — для игр используйте SceneKit или SpriteKit.
UIDynamicAnimator — центральный класс UIKit Dynamics. Он инициализируется с reference view (обычно view контроллера) и управляет всеми активными поведениями. Каждый кадр UIDynamicAnimator пересчитывает позиции, скорости и ускорения всех добавленных элементов с учётом физических законов.
Метод addBehavior добавляет одно поведение (или сложный UIDynamicBehavior), removeBehavior — удаляет. Animator автоматически приостанавливается, когда все объекты достигают состояния покоя (continue без столкновений и сил). Метод delegate — UIDynamicAnimatorDelegate — оповещает о паузе и возобновлении симуляции.
Любой объект, участвующий в физике, должен реализовывать протокол UIDynamicItem. UIView и UICollectionViewLayoutAttributes уже реализуют его. Протокол требует свойства: bounds, center, transform. Если объект кастомный — реализуйте протокол вручную.
UIKit Dynamics включает семь встроенных типов поведений, каждое из которых моделирует определённый физический эффект. Поведения можно комбинировать: например, гравитация + столкновения + упругость создают эффект падающих и отскакивающих объектов.
| Behavior | Физический эффект | Ключевые параметры |
|---|---|---|
| UIGravityBehavior | Гравитация (вектор силы) | gravityDirection (dx, dy), magnitude |
| UICollisionBehavior | Столкновения объектов и границ | collisionMode, translucence, collisionDelegate |
| UIAttachmentBehavior | Связь (пружина/трос) | anchorPoint, length, damping, frequency |
| UISnapBehavior | Притяжение к точке с демпфированием | snapPoint, damping (0-1) |
| UIPushBehavior | Толчок/импульс (непрерывный или мгновенный) | pushDirection, magnitude, mode |
| UIDynamicItemBehavior | Физические свойства объекта | elasticity, friction, density, resistance |
| UIFieldBehavior | Силовые поля (вихрь, магнит, радиус) | position, strength, falloff, region |
Для реалистичной физики объекта нужно несколько поведений одновременно. Например, для падающей карты: UIGravityBehavior (сила тяжести), UICollisionBehavior (столкновение с дном), UIDynamicItemBehavior (elasticity: 0.4 для отскока). Все поведения добавляются к одному UIDynamicAnimator.
Swift код для UIKit Dynamics создаёт UIDynamicAnimator и добавляет поведения. Пример ниже демонстрирует гравитацию с несколькими объектами, столкновениями и кастомными физическими свойствами.
import UIKit
class PhysicsViewController: UIViewController {
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
// 1. Создаём аниматор с reference view
animator = UIDynamicAnimator(referenceView: view)
// 2. Создаём падающие объекты
let redView = UIView(frame: CGRect(x: 100, y: 50, width: 60, height: 60))
redView.backgroundColor = .systemRed
redView.layer.cornerRadius = 8
view.addSubview(redView)
let blueView = UIView(frame: CGRect(x: 200, y: 30, width: 60, height: 60))
blueView.backgroundColor = .systemBlue
blueView.layer.cornerRadius = 8
view.addSubview(blueView)
// 3. Гравитация
let gravity = UIGravityBehavior(items: [redView, blueView])
gravity.gravityDirection = CGVector(dx: 0, dy: 1)
gravity.magnitude = 0.8
animator.addBehavior(gravity)
// 4. Столкновения
let collision = UICollisionBehavior(items: [redView, blueView])
collision.translatesReferenceBoundsIntoBoundary = true
collision.collisionDelegate = self
animator.addBehavior(collision)
// 5. Физические свойства
let itemBehavior = UIDynamicItemBehavior(items: [redView, blueView])
itemBehavior.elasticity = 0.6
itemBehavior.friction = 0.3
itemBehavior.density = 1.0
animator.addBehavior(itemBehavior)
// 6. Snap-поведение по тапу
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tap)
}
@objc
func handleTap(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: view)
// Snap-поведение для каждого объекта
for subview in view.subviews where subview is UIView {
animator.removeAllBehaviors()
let snap = UISnapBehavior(item: subview, snapTo: point)
snap.damping = 0.5
animator.addBehavior(snap)
}
}
}
extension PhysicsViewController: UICollisionBehaviorDelegate {
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item1: UIDynamicItem,
with item2: UIDynamicItem,
at point: CGPoint) {
print("Collision at: (point)")
}
}Пример создаёт два View с гравитацией, столкновениями и физическими свойствами. UISnapBehavior при тапе притягивает объекты к точке касания с демпфированием 0.5. UICollisionBehaviorDelegate отслеживает начало столкновений для звуковых и визуальных эффектов.
UIKit Dynamics применяется в iOS-приложениях для неигровой физики интерфейса. Популярные сценарии: анимация стопки карт (UISnapBehavior для притяжения к центру), встряхивание экрана при ошибке (UIDynamicItemBehavior + UIPushBehavior), эффект «падающих звёзд» в онбординге (gravity + collision + field behavior).
Для производительности UIKit Dynamics рекомендуется не более 15-20 одновременных объектов с физикой. Каждый объект требует расчёта коллизий и сил на каждом кадре. При превышении лимита используйте CALayer вместо UIView — Core Animation обрабатывает слои эффективнее.
Часто задаваемые вопросы
UIKit Dynamics моделирует физические взаимодействия (гравитация, столкновения, силы) на основе симуляции твёрдых тел. Core Animation — анимация свойств CALayer (position, opacity, transform) по заданной временной кривой. Dynamics подходит для интерактивной физики, Core Animation — для предопределённых переходов.
Прямой поддержки UIKit Dynamics в SwiftUI нет. Для физических эффектов используйте UIKitView + UIDynamicAnimator внутри UIViewRepresentable, либо кастомные анимации через Animation.spring() и withAnimation() в SwiftUI.
Вызовите animator.removeAllBehaviors() — это удалит все активные физические поведения. Animator автоматически приостанавливается, когда все объекты достигают покоя. Для временной паузы используйте свойство animator.isPaused или удалите отдельные поведения.
Apple рекомендует не более 15-20 объектов с полной физикой (гравитация + столкновения + силы). Для массовых анимаций используйте UIFieldBehavior — он рассчитывает силы централизованно, без попарных коллизий, что снижает нагрузку на CPU.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также