CLOSE SEARCH

UIKit Dynamics #1 – More Realistic Animations in iOS 7

iOS의 애니메이션 기능은 정말 뛰어납니다. 특별히 어려운 소스코드를 작성하지 않고도 부드러운 애니메이션을 만들 수 있고, 사용자들은 이러한 에니메이션을 통해 멋진 시각적 피드백을 제공받습니다. 안드로이드나 윈도우 모바일 역시 에니메이션 기능을 제공하지만, 품질이나 개발 편의성 면에서 iOS의 기능을 따라오기는 힘들어 보입니다. 더욱이 이번 WWDC 2013에서 발표된 UIKit Dynamics와 Custom View Controller Transitions 기능으로 인해 에니메이션에 있어서만큼은  iOS가 이전보다 몇발 더 앞서가게 되었습니다. 이번 글에서는 UIKit Dynamics에 대해서 알아봅니다.

Apple은 UIKit Dynamics에 대해 다음과 같이 정의하고 있습니다.

A composable, reusable, declarative, real-world inspired animation, and interaction system

어렵습니다. 그냥 제가 공부하면서 느낀 정의는 이런것입니다.

iOS에서 현실에 가까운 에니메이션과 상호작용을 구현할 수 있도록 도와주는 새로운 기능!

UIKit Dynamics를 사용하면 뷰에 중력을 추가해서 어떤 방향으로 자유낙하하도록 만들수도 있고, 한쪽 면에 충돌하여 바닥에 떨어지도록 만들수도 있습니다. 마치 뷰에 스프링이 달린것처럼 튕기는 효과를 줄수도 있습니다. 예전처럼 이동, 감속, 가속 등으로만 이루어진 에니메이션에 중력, 탄성과 같이 물리법칙을 적용하여 훨씬 더 현실적인 효과를 구현할 수 있게 되었습니다. iOS에 포함된 2D엔진이 복잡한 처리를 모두 해주기 때문에, 얻게 되는 효과에 비해 작성해야 하는 코드의 양은 상당히 적습니다.

 

Main Classes & Protocols

UIKit에는 UIKit Dynamics를 구현하기 위한 다양한 클래스와 프로토콜이 추가되었습니다. 우선 가장 중요한 두개의 클래스와 UIKit Dynamics와 상호작용 하기위해 반드시 구현해야 하는 프로토콜에 대해 알아보겠습니다.

UIDynamicItem  Protocol

UIDynamicItem 프로토콜은 UIKit Dynamics와 상호작용하는 객체들이 반드시 구현해야 하는 프로토콜입니다. iOS7의 UIView와 UICollectionViewLayoutAttributes 클래스는 기본적으로 이 프로토콜을 구현하고 있습니다. 그래서 이 두개의 클래스와 여기에서 파상되는 클래스의 객체들은 기본적으로 UIKit Dynamics를 적용할 수 있습니다.

이 프로토콜은 bounds, center, transform의 3가지 속성으로만 이루어져 있습니다. 이 속성들은 UIKit이 아이템에 에니메이션을 적용하는데 사용됩니다. 모든 속성은 에니메이션이 올바르게 구성될 수 있도록 올바른 초기값을 가지고 있어야하며, 에니메이션이 진행중인 동안에는 UIKit에 의해 값이 자동적으로 업데이트 되기 때문에 직접 값을 변경하는 코드들은 모두 무시됩니다.

 

UIDynamicAnimator

UIDynamicAnimator 클래스는 UIKit Dynamics 효과를 구성하는 Dynamic Behavior들을 관리하고, iOS의 물리엔진과 상호작용하면서 지정된 에니메이션을 생성하고 실행하는 에니메이션 컨텍스트를 제공합니다. 간단히 말해서 전체 에니메이션 효과를 관리하는 관리자 객체라고 볼 수 있습니다.

UIDynamicAnimator는 초기화에 사용되는 객체의 종류에 따라 3가지 방식으로 초기화 할 수 있습니다.

1. UIView 또는 여기에서 파생되는 객체에 UIKit Dynamics 효과를 적용하고자 하는 경우에는  initWithReferenceView: 메소드를 사용합니다. 이 객체를 통해 실행되는 에니메이션은 레퍼런스 뷰의 좌표체계 내에서 실행됩니다.

2. UICollectionView 또는 여기에서 파생되는 객체에 UIKit Dynamics 효과를 적용하고자 하는 경우에는 initWithCollectionViewLayout: 메소드를 사용합니다. 이 메소드를 통해 초기화된 객체를 Collection View Animator라고 부르며, 파라미터로 전달된 컬렉션 뷰 레이아웃은 에니메이터의 좌표체계에 추가됩니다. 그리고 연관된 Dynamic Item 들은 반드시 UICollectionViewLayoutAttributes 객체 또는 여기에서 파생된 객체여야 합니다.

3. 마지막으로 UIDynamicItem 프로토콜을 구현하는 객체를 사용하고자 하는 경우에는 init 메소드를 사용합니다. 이 에니메이터는 특정 뷰와 연관되지 않은 가상의 좌표체계를 사용합니다.

Dynamic Animator는 자신에게 추가된 에니메이션들의 실행을 관리합니다. 새로운 Dynamic Behavior 또는 Dynamic Item이 추가되거나 제거될 때, 연관된 에니메이션이 자동적으로 실행됩니다. 그리고 모든 에니메이션이 완료된 경우 자신의 동작을 일시정지합니다. UIDynamicAnimatorDelegate 프로토콜을 구현하면 에니메이터의 시작과 일시정지 시점에 원하는 작업을 구현할 수 있습니다.

 

UIDynamicBehavior

Dynamic Animator에는 다수의 Dynamic Behavior를 추가할 수 있습니다. UIDynamicBehavior 클래스를 통해 구현된 Dynamic Behavior는 Dynamic Item에 적용되는 에니메이션을 구성하는 역할을 합니다. iOS에서는 중력 에니메이션이나 스프링 에니메이션 등을 쉽게 구현할 수 있도록 미리 정의된 Dynamic Behavior들을 제공합니다.

[list style=”star”]

  • UIAttachmentBehavior
  • UICollisionBehavior
  • UIGravityBehavior
  • UIPushBehavior
  • UISnapBehavior
  • UIDynamicItemBehavior

[/list]

위에 나열된 Dynamic Behavior들을 사용하는 것이 가장 간단하지만, 직접 원하는 효과를 구현하고자 하는 경우에는 UIDynamicBehavior 클래스를 상속하는 클래스를 직접 구현할 수도 있습니다.

또한, addChildBehavior: 메소드를 통해 하나 이상의 Dynamic Behavior를 자식으로 추가하여 복잡한 에니메이션을 구성할 수도 있습니다. 이와 동일한 효과를 얻기 위해서 각 Dynamic Behavior를 어느 한 Dynamic Behavior의 자식으로 추가하지 않고 직접 Dynamic Animator에 추가하는 방식을 사용할 수도 있습니다. 두 가지 방식에는 성능차이가 거의 없기 때문에 자신이 원하는 방식을 사용하면 됩니다.

Dynamic Behavior는 Dynamic Animator에 추가되면 자동으로 에니메이션을 실행하고, 제거되면 실행중인 에니메이션을 중지합니다. startAnimation이나 stopAnimation과 같이 수동으로 애니메이션을 제어하는 메소드는 제공되지 않습니다. 그리고 모든 Dynamic Behavior는 애니메이션이 실행되는동안 매 사이클마다 호출되는 특별한 블럭을 가집니다. 이 속성블럭은 action이라는 이름으로 제공되며, 자주 호출되는만큼 성능에 영향을 줄 수 있기 때문에 신중하게 사용해야 합니다.

 

Architecture

앞에서 설명한 3가지 항목들은 다음과 같이 구성됩니다.

uikit_dynamics_architecture

UIDynamicAnimator는 하나 이상의 UIDynamicBehavior를 관리하며 자신과 연관된 레퍼런스 뷰를 가집니다. 이 레퍼런스 뷰는 실제 에니메이션이 수행되는 좌표체계를 제공하는 역할을 합니다. UIDynamicBehavior는 실제 에니메이션이 적용될 Dynamic Item을 가지고 있으며, Dynamic Item들은 반드시 UIDynamicItem 프로토콜을 따르는 객체여야 합니다. 위의 그림에서 View라고 적힌 초록색 박스가 Dynamic Item에 해당되며, 일반적으로 UIView 또는 UICollectionViewLayoutAttribute 객체를 나타냅니다.  그리고 Dynamic Behavior는 다수의 Dynamic Item과 연관될 수 있으며, 마찬가지로 Dynamic Item 역시 다수의 Dynamic Behavior와 연관될 수 있습니다.

 

Simple 3 Steps

UIKit Dynamics를 적용하는 과정은 크게 3단계로 구분할 수 있습니다. 아래의 예제는 두개의 뷰 사이의 충돌 에니메이션을 구성하기 위해 Collision Behavior를 추가하는 예제이지만, 나머지 다른 Behavior들도 각각 자신의 속성을 설정하는 부분만 다를뿐 이와 동일한 방법으로 사용할 수 있습니다.

1. Dynamic Animator 생성 및 초기화 – Code1은 뷰 컨트롤러의 뷰를 레퍼런스 뷰로 사용하는 Dynamic Animator를 생성합니다.

2. Dynamic Behavior 생성 및 초기화 – Code2는 뷰 컨트롤러의 뷰에 속해있는 두개의 뷰(box1, box2)와 연관된 Collision Behavior를 생성합니다. 그리고 레퍼런스 뷰의 영역과 동일한 영역을 자신의 충돌처리 영역으로 설정합니다.

3. Dynamic Animator에 Dynamic Behavior 추가 – Code3과 같이 addBehavior 메소드를 통해 Dynamic Animator에 추가되면 그 즉시 Dynamic Behavior에 구성된 에니메이션이 실행됩니다.

한가지 주의해야 할 점은 UIDynamicAnimator 객체나 UIDynamicBehavior 객체 모두 적절히 retain 되어야 한다는 것입니다. 그렇지 않은 경우에는 애니메이션이 동작하지 않게됩니다.

Filed under: Apple WWDC 2013, iOS