View Controller


    View controller는 앱의 UI를 꾸미는 view들을 관리한다. 개발할 기능과 시각적 요소를 제공하기 위해서 view controller를 상속받아 클래스를 구현한다. view controller는 관리하고 있는 view들과 엮여 있으며 event를 처리하기 위한 Responder chain에 관여한다. view controller는 UIResponder 객체로서, 해당 view controller의 root view와 super view 사이의 Responder chain에 위치한다. view controller의 view가 event를 처리하지 않는다면 해당 event를 super view로 넘길 수 있다. 그리고 다른 view controller를 container view controller에 표시할 수 있다.


Responder Chain




Storyboard와 Nib file


    Storyboard를 사용하면 view controller의 view들을 정의할 수 있고, 각 view controller의 관계를 segue를 통하여 정의할 수 있다. Nib 파일을 사용하면 각 view controller와 연관된 view들을 정의할 수 있다. storyboard처럼 각 view controller간의 관계를 정의할 수 없다. storyboard나 nib이 아닌 코드로 custom view를 정의할 경우, view controller의 view들은 loadView() 메소드에서 정의합니다. view controller의 root view 또한 loadView()에서 생성한다.



View controller와 View


    view controller는 자신이 가지고 있는 view들의 유일한 소유자이다. 이 소유권은 view controller가 해제될 때까지 유지된다. nib 파일이나 storyboard에 view를 정의했을 경우, view controller에서 view를 불러올 때 복사본이 생성되어 소유하게 된다. 즉, 다른 view controller에서도 사용 가능하여 재사용성이 높아집니다. 하지만 view controller 내부에 정의된 view의 경우에는 해당 view controller만 소유할 수 있다. root view는 view controller에 정의된 전체 영역에 맞게 자동으로 맞춰진다. root view에 올라가는 각 subview들은 autolayout과 같은 기능을 사용하여 개발자가 직접 사이즈와 위치를 정의할 수 있다.



addSubView와 addChildViewController (Container View Controller)





참고 : Apple documents - UIViewController

addSubview & addChildViewController


    addSubview는 view를 view hierarcky에 추가한다. addChildViewController는 Container View Controller에 child view controller를 추가한다. 전자의 경우, 하나의 view controller에서 event를 관리한다. 후자의 경우, 각각의 view controller들이 자신이 소유하고 있는 view의 event를 따로 관리하게 된다. 그리고 각 child view controller를 소유하고 있는 view controller를 container view controller라고 한다.


    우리가 가장 흔하게 볼 수 있는 container view controller의 예가 tab bar controller / navigation controller 등이 있다. 각 tab별로 view controller를 추가한다. 각 view controller는 해당 tab이 눌리면 화면 상에 추가되어 사용자 event를 각자 처리하게 된다. 이와는 별개로 사용자의 event를 받기만할 뿐, 따로 처리하는 로직을 분리하고 싶지 않으면 해당 view를 addSubview로 추가한다.




Container View Controller


    UIViewController를 상속한 클래스는 container view controller로 동작할 수 있다. container view controller는 자신이 소유하고 있는 child view controller의 내용물 (view, event 등)을 표현하는 로직을 관리한다. child view controller의 view는 contain view controller의 view와 연계되어 표시된다. 해당 container view controller는 child view controller들과 연계될 수 있도록 public interface로 선언해야 한다. container view controller의 interface들을 public으로 선언함으로써 child view controller들이 container view controller 구현부의 동작에 상관없이 각자의 역할을 수행한다.





    위 그림처럼 child view controller를 추가하면 된다. child view controller의 view가 view hierarcky에 추가되기 전에 container view controller에 추가해야한다. 이 과정이 선행되야 contain view controller는 자신이 관리하는 view와 child view controller에게 event를 전달할 수 있다. 마찬가지로 child view controller의 view가 제거된 후에는 child view controller에서 자기자신을 container view controller에서 제거해야 한다. 제거를 위한 메소드들은 child view controller가 아니라, container view controller에 의해서만 호출해야 Containment 동작에 예외 케이스를 줄일 수 있다.


    


추후, sample code 및 추가 주석 필요


    UIViewPropertyAnimator를 사용해서 사용자의 제스처와 유기적인 애니메이션 구현이 가능합니다. UIViewPropertyAnimator는 작년 (2016)에 발표된 API 입니다. 타이밍 펑션을 지원하여 베지어 곡선을 사용한 animation 커스터마이징이 가능합니다. 그리고 사용자의 인터랙션과 함계 유기적인 animation 동작이 가능합니다.


    fractionComplete라는 animation 프로퍼티로 사용자의 제스처에 따른 진행 경과를 지정해 줄 수 있습니다. 코드로 구현한 animation의 경우, 사용자의 동작이 끝나는 시점은 가져왔지만 제스처에 의해 미리 진행된 animation의 경과를 가져올 수 없었습니다. 하지만 fractionComplete를 사용하면 사용자가 20%까지 버튼을 움직인 경우, 이 부분부터 이어서 나머지 80%의 animation 동작을 지정할 수 있습니다. 뿐만 아니라 실행되고 있는 animation을 중단하고 사용자의 제스처를 수행할 수도 있습니다. 구현 방식은 아래와 같습니다.




    먼저 인터랙션을 사용하여 애니메이션 구현입니다.제스쳐, 3D 터치를 적용할 수도 있습니다. 기본은 pausing과 continue라는 2가지의 개념에 있습니다. 실행하고자하는 animation을 추가하고 pausing을 호출합니다. 추가된 animation은 실행이 정지 되어 있습니다. 이 상 태로 사용자의 제스처에 따라 fraction 값을 조정합니다. 사용자의 제스처 동작이 끝나는 시점에 fraction부터 지정된 animation이 수행될 수 있도록 continue를 호출합니다. 위의 과정을 통해 사용자의 제스처의 영향을 받지 않고, 제스처에 이어서 미리 지정했던 animation의 수행이 가능합니다.


-pausing은 애니메이션이 시작된 상태지만 동작은 하지 않습니다.

-praction은 실제 정의된 애니메이션의 중간 과정을 애니메이터에 지정하여 알려줍니다.

-continue는 실제 정의된 상태의 지점 (fraction)에서 지정된 애니메이션을 수행




    인터럽터블 애니메이션은 진행 중인 애니메이션을 사용자의 제스처에 의해 interrupt하는 것을 말합니다. 간단한 예로 웹뷰에서 스크롤 animation이 사용자의 제스처에 의해 정지되는 것을 확이하실 수 있습니다. 이는 사용자의 제스처가 들어오는 지점에서 animation을 pausing을 한 다음 현 시점에 fraction을 저장합니다. 그리고 사용자의 제스처에 따라 움직이다가 제스처가 끝나는 시점에 continue를 호출하여, 수행중이던 animation을 제스처에 이어 수행합니다.


-애니메이션에 인터럽트가 걸리는 시점 (사용자의 제스처가 시작되는 지점)에 pausing을 수행합니다.

-praction은 실제 정의된 애니메이션의 중간 과정을 애니메이터에 지정하여 알려줍니다.

-continue는 실제 정의된 상태의 지점에서 지정된 애니메이션을 수행합니다.




    UIViewPropertyAnimator에는 새로운 property가 2개 추가됬습니다. 하나는 scrupsLineary이고, 다른 하나는 puaseOnCompletion입니다.

scrupsLineary (Bool) : pauseed animation에 선형적으로 animation을 수행할건지, timing function을 적용할건지 지정하는 프로퍼티입니다.

puaseOnCompletion (Bool) : 모든 animation은 animation 수행이 완료 되어야 completion 동작을 수행합니다. 하지만 puaseOnCompletion이 true이면 puase 상태서 complation이 수행됩니다. pause로 인한 animation의 종료를 알고 싶으면 KVC를 사용하여, 'running'이라는 keypath를 이용합니다.



    이외에 spring animation을 이용하여 스프링 효과를 줄 수 있습니다. 탄력적인 움직임을 주는 critical dumping은 dumping 값을 1.0을 주면 되고, 지정된 범위를 벗어나서 튕기는 spring 효과는 dumping 값을 1,0보다 작게 주면 됩니다. 이외에 UIVisualEffectView를 사용하여 view에 blur 효과와 같은 효과들을 줄 수 있는데, 이는 UIVisualEffect로 정의한 animator를 UIViewEffectView에 추가해주면 수행됩니다. UITimingCurveProvider를 사용하여 커스터마이징한 timing function을 추가할 수 있습니다.



    이번에 iOS 11에서 두드러지는 animation 중에 하나가 사용자의 interaction에 따라 변화하는 label입니다. 이는 Veiw Morping을 이용한 것입니다. View Morping은 2개의 view를 하나의 view가 변하는 것처럼 보여지게 하는 것입니다. 사용자의 interaction에 따라 각 2개의 label과 2개의 animator를 구현합니다. 그리고 2개의 animator를 concatenating을 사용하여 엮습니다. 


    WWDC에서는 animation을 사용하는 데 있어, tip도 소개하고 있습니다. 먼저 layer에서 radius curve와 masked corner를 사용하여 animation을 줄 수 있습니다. 그리고 key frame animation을 사용하여 실행하고자 하는 animation을 미리 종료하거나 실행을 지연 시킬 수 있습니다. 또한 additive animation이라고 소개된 방법을 사용하면 수행 중에 다음 수행할 animation을 지속적으로 추가할 수 있으며, 이를 하나의 timing function으로 동작하게 만들 수 있습니다. 

'WWDC > 2017' 카테고리의 다른 글

[iOS] Visually Rich User Experiences  (0) 2017.06.21
[iOS] Advanced Animation with UIKit  (0) 2017.06.20
[iOS] Core ML in WWDC 2017  (0) 2017.06.20

+ Recent posts