View Controller Programming Guide for iOS - View Controller Definition
Defining Your Subclass
앱의 컨텐츠를 나타내기(present) 위해서 UIViewController
의 서브클래스를 사용한다. 대부분의 VC(View Controller)
는 content view controller이고, 이들은 자신의 모든 view
를 소유하며 view
에 있는 데이터에 대한 책임도 가진다. 이와 반대로 container view controller는 자신의 모든 view
를 소유하지 않는다. 이들의 몇몇 view
는 다른 VC
에 의해 관리된다. content/container view controller를 정의하는 대부분의 과정은 서로 같고, 이 과정을 앞으로 살펴 볼 것이다.
content view controller의 경우 가장 흔한 부모 클래스는 다음과 같다:
VC
의 메인view
가 테이블인 경우UITableViewController
를 사용하라.VC
의 메인view
가 컬레션 뷰인 경우UICollecntionViewController
를 사용하라.- 모든 다른
VC
를 위해선UIViewController
를 사용하라.
Defining Your UI
VC
에 대한 UI를 시각적으로 정의하는 것은 Xcode의 스토리보드 파일을 사용하여 이루어진다. 코드로(proprogrammatically) UI를 생성할 수도 있지만, 스토리보드를 사용하면 직관적이고 빠르게 UI를 파악할 수 있다.
다음 그림은 간단한 스토리보드의 구성을 보여준다. 각각의 사각형 영역은 VC
와 VC
의 view
를 표현한다. VC
사이의 화살표는 둘 사이의 관계(Relationships)와 세그웨이(segues)이다. 관계는 container view controller를 자식 VC
와 연결하고, 세그웨이는 VC
사이의 이동을 가능하게 한다.
Handling User Interactions
VC
가 이벤트나 액션을 직접 처리하는 일은 흔치 않고, 보통 다음과 같은 방법을 통해서 이벤트를 처리한다.
**VC
는 액션 메소드를 정의하여 higher-level 이벤트를 처리한다.** 액션 메소드는 다음에 대해 응답한다.- Specific actions.
view
는 특정 상호작용을 리포트하기 위해 액션 메소드를 호출한다. - Gesture recognizers. Gesture recognizers는 제스처의 현재 상태를 리포트하기 위해 액션 메소드를 호출한다. 제스처의 진행 상태나 제스처의 결과를 처리하기 위해서는
VC
를 사용해라.
- Specific actions.
**VC
는 시스템이나 다른 객체가 전송하는 알림(notifications)을 관찰(oberve) 한다.** 알림은 변화를 리포트하고,VC
의 상태를 업데이트하는 방법이다.**VC
는 다른 객체를 위한 data source 혹은 delegate 역할을 한다.**VC
는 종종 테이블과 컬렉션 뷰를 위한 데이터를 관리하기 위해 사용된다. 또한, 대리자에게 갱신된 위치 값을 전달하는CLLocationManager
같은 객체의 대리자(delegate) 역할을 하기도 한다.
종종 이벤트에 대한 응답으로 view
의 컨텐츠를 갱신하기도 한다. VC
에 후에 수정할 view
에 대한 outlet
을 정의하여 이를 수행할 수 있다.
class MyViewController: UIViewController {
@IBOutlet weak var myButton : UIButton!
@IBOutlet weak var myTextField : UITextField!
@IBAction func myButtonAction(sender: id)
}
Displaying Your View at Runtime
스토리보드는 VC
의 view
를 로드하고 표시하는 과정을 매우 간단하게 해준다. UIKit은 스토리보드 파일의 view
를 필요할 때 자동으로 로드한다. 로딩 과정에서 UIKit은 다음과 같은 작업을 수행한다.
- 스토리보드 파일의 정보를 사용하여
view
를 인스턴스화 한다. - 모든 outlet, action을 연결한다.
VC
의view
프로퍼티에Root View
를 할당한다.VC
의awakeFromNib
메소드를 호출한다.VC
의viewDidLoad
메소드를 호출한다.
VC
의 view
를 화면에 표시하기 전에 UIKit은 view
를 위한 추가적인 작업을 할 수 있도록 해준다. UIKit은 다음의 작업들을 수행한다.
viewWillAppear:
메소드를 호출한다.view
가 막 화편에 표시될 것이라는 것을 알려준다.view
의 layout(배치)를 갱신한다.view
를 화면에 표시한다.view
가 화면에 표시되면viewDidAppear:
메소드를 호출한다.
Managing View Layout
view
의 크기와 위치가 변할때, UIkit은 view
계층의 layout(배치) 정보를 업데이트 한다. Auto Layout을 사용하여 구성된 view
의 경우, UIkit은 Auto Layout 엔진을 통해서 현재 제약조건에 따라 layout을 업데이트 한다.
Layout 작업 동안, UIkit은 layout과 관련한 추가적인 작업을 수행할 수 있도록 몇몇 포인트를 알려준다. 이 알림을 사용해서 layout 제약조건을 수정하거나 제약조건이 적용된 후에 최종 마무리 작업을 수행할 수 있다. Layout 작업 중에 UIKit은 다음과 같은 것들을 한다.
VC
와view
의 trait collection을 갱신한다. 필요하다면.VC
의viewWillLayoutSubviews
메소드를 호출한다.- 현재
UIPresentationController
객체의containerViewWillLayoutSubviews
메소드를 호출한다. VC
의 root view의layoutSubviews
를 호출한다.- 계산된 layout 정보를
view
에`적용한다. VC
의viewDidLayoutSubviews
메소드를 호출한다.- 현재
UIPresentationController
객체의containerViewDidLayoutSubviews
메소드를 호출한다.
VC
는 viewWillLayoutSubviews
와 viewDidLayoutSubviews
메소드를 사용하여 layout 작업에 영향을 줄수 있는 추가적인 업데이트를 수행할 수 있다. Layout 전에 view
를 추가/제거 하거나, 크나 위치를 업데이트 하거나, 제약조건을 업데이트하는 등의 작업을 할 수 있다. Layout 후에는, table 데이터를 리로드 하거나, view
의 컨텐츠를 업데이트 하거나, view
의 위치와 크기에 대한 마지막 조절을 할 수도 있다.
Layout을 효율적으로 관리하는 팁은 다음과 같다:
- Auto Layout을 사용해라. Auto Layout을 사용하여 제약조건을 생성하는 것은 다양한 크기의 화면에서 컨텐츠를 위치시킬 수 있는 유연하고 쉬운 방법이다.
- Top, bottom layout guides를 활용해라. 이 가이드를 사용하는 것은 언제나 컨텐츠가 화면상에 보여지는 것을 보장한다. status bar, navigation bar의 높이를 고려해야하는 경우, tab bar, toolbar의 높이를 고려해야하는 경우에 중요하다.
**view
를 추가/제거 할 때 제약조건을 업데이트 하는 것을 기억해라.** 만약view
를 동적으로 추가/삭제 한다면, 대응하는 제약조건을 업데이트 하는 것을 기억해라.**VC
의view
를 애니메이팅 할때는 일시적으로 제약조건을 제거해라.** UIKit Core Animation을 사용하여view
에 애니메이션을 줄 경우, 애니메이션 동작 동안에는 제약조건을 제거하고, 애니메이션이 끝나면 추가해라. 만약 위치나 크기가 애니메이션 중간에 바뀐다면, 제약조건을 업데이트 해야 하는 점을 명심해라.
Managing Memory Efficiently
다음의 표에는 메모리를 할당하거나 할당 해제 작업을 주로 하게될 UIViewController
의 메소드가 나열되어 있다. 대부분의 할당 해제에는 객체에 대한 강한 참조 제거가 포함된다. 객체에 대한 강한 참조를 제거하려면 해당 객체를 가리키는 프로퍼티와 변수를 nil
로 설정하면 된다.
Task | Methods | Discussion |
---|---|---|
VC 에 필수적인 중요한 데이터 구조를 할당하는 작업 |
초기화 메소드 | 사용자 지정 초기화 메서드는 항상 VC 객체가 주어진 정확한 상태로 만드는 책임이 있다. 초기화 메소드를 사용하여 정확한 작업을 보장하는 데 필요한 데이터 구조를 해라. |
view 에 나타날 데이터를 할당하거나 로드 |
viewDidLoad |
이 메소드를 사용하여 표시할 데이터 객체를 로드해라. |
메모리 부족 알림에 대한 반응 | didReceiveMemoryWarning |
이 메소드를 사용하여 VC 와 관련된 모든 noncritical 객체를 할당 해제해라. 할 수 있는 가장 많은 메모리를 할당 해제 해라 |
VC 에 필수적인 중요한 데이터 구조를 반환하는 작업 |
dealloc |
VC 클래스를 마지막 순간에 정리하려면이 메서드를 오버라이드 해라. 시스템이 클래스의 인스턴스 변수와 프로퍼티에 저장된 객체를 자동으로 해제하므로 명시 적으로 해제 할 필요가 없다. |
Implementing a Container View Controller
Container View Controller는 여러 VC
의 컨텐츠를 묶어서 하나의 UI로 보여주는 방법이다.
Designing a Custom Container View Controller
Container View Controller는 루트 뷰와 컨텐츠를 관리한다는 점에서 content view controller와 거의 같다. 차이점은 Container View Controller는 다른 VC
로부터 컨텐츠의 일부를 가져온다는 것이다. 가져오는 컨텐츠는 다른 VC
의 view
로 제한되며 view
계층 구조 내에 포함된다. Container View Controller는 view
의 크기와 위치만 설정하고 원래 VC
가 해당 view
내의 컨텐츠를 관리한다.
Container View Controller를 설계할 때, 컨테이너와 자식 (VC
)의 관계를 이해해야 한다. 이 관계는 컨텐츠가 화면에 표시되는 방식과 컨테이너가 어떻게 내부적으로 VC
를 관리하는지 알 수 있도록 도와준다. Container View Controller 설계 과정에서 다음과 같은 사항을 고려해라.
- 컨테이너, 자식의 역할.
- 동시에 몇개의 자식이 표시되는지.
- Sibling
VC
사이의 관계. - 컨테이너에
VC
가 어떻게 추가/삭제 되는지. - 자식의 크기와 위치가 변할 수 있는지. 어떤 조건에서 변화가 발생하는지.
- 컨테이너가 꾸며거나 이동을 위한
view
를 제공하는지. - 어떤 종류의 커뮤니케이션이 컨테이너와 자식 사이에서 발생하는지. 컨테이너는 특정 이벤트 발생을 자식에게 알려야하는지.
- 컨테이너의 외형이 다른 방식으로 구성될 수 있는지. 있다면 어떻게 구성해야 하는지.
Example: Navigation Controller
UINavigationController
객체는 계층화된 데이터 셋 사이의 이동을 지원한다. 네비게이션 인터페이스는 한번에 하나의 자식(VC
)만 표시한다. 인터페이스 상단에 있는 네비게이션 바는 데이터 계층에서 현재 위치를 표시하고 한 단계 뒤로 갈 수 있는 뒤로가기 버튼을 표시한다. VC
사이의 이동은 네비게이션 컨트롤러와 자식이 함께 관리한다. 자식 VC
는 발생하는 이벤트에 따라 네비게이션 컨트롤러에 새로운 VC
를 push 할지를 요청한다. 자식은 새로은 VC
의 컨텐츠 구성을 관리하고, 네비게이션 컨트롤러는 전환 애니메이션을 관리한다. 네비게이션 컨트롤러는 네비게이션 바를 관리하기도 한다.
이 그림은 네비게이션 컨트롤러와 view
의 구조를 보여준다.
Example: Split View Controller
UISplitViewController
객체는 두 VC
의 컨텐츠를 master-detail 형태로 표시한다. 이러한 배치에서 master에 해당하는 VC
의 컨텐츠가 detail에 해당하는 VC
의 컨텐츠를 결정한다. 두 VC
는 현재 환경에 따라 다르게 표시된다. regular horizontal 환경의 경우, 두 VC
가 한번에 표시될 수 있지만, compact한 환경에서는 하나의 VC
만 화면에 표시된다.
Configuring a Container in Interface Builder
설계 시점에 parent-child 관계의 컨테이너를 생성하기 위해서는 다음 그림처럼 스토리보드에 컨테이너 뷰 객체를 추가하면 된다. 컨테이너 객체는 자식 뷰 컨트롤러의 컨텐츠를 나타내는 플레이스홀더이다.
VC
와 함께 컨테이너 뷰가 로드할 때, 인터페이스 빌더는 관련된 자식 뷰 컨트롤러도 함께 로드한다. 자식은 부모와 함께 인스턴스화 되어야 적절한 parent-child 관계가 형성될 수 있다.
Implementing a Custom Container View Controller
컨테이너 뷰 컨트롤러를 실행하기 위해서는 반드시 뷰 컨트롤러와 자식 뷰 컨트롤러 관계를 형성해야 한다. 자식 뷰 컨트롤러의 뷰를 관리하기(manage) 전에 이 관계는 설립돼있어야 한다. UIkit은 이 관계를 통해서 뷰 컨트롤러가 자식의 크기와 위치를 관리한다는 것을 알게된다. 이 관계는 인터페이스 빌더에서 형성하거나 프로그래밍을 통해서 생성할 수 있다. 프로그래밍으로 관계를 생성할 때는 뷰 컨트롤러의 설정 단계에서 명시적으로 자식 뷰 컨트롤러를 추가/삭제 해줘야 한다.
Adding a Child View Controller to Your Content
프로그래밍으로 자식 뷰 컨트롤러를 컨텐츠에 추가하기 위해서는 다음을 통해서 관련된 뷰 컨트롤러 사이에 부모-자식(parent-child) 관계를 생성해라.
- 컨테이너 뷰 컨트롤러의
addChildViewController:
메소드를 호출해라. 이 메소드는 UIkit에게 컨테이너 뷰 컨틀로러가 자식 뷰 컨트롤러의 뷰를 관리한다는 것을 알려준다. - 컨테이너 뷰 계층 구조에 자식의 루트 뷰를 추가해라. 이 과정에서 자식 뷰의 프레임 크기와 위치를 설정해야함을 기억해라.
- 자식의 루트 뷰의 크기와 위치를 위한 제약조건을 추가해라.
- 자식 뷰 컨트롤러의
didMoveToParentViewController:
메소드를 호출해라.
오토레이아웃을 사용한다면, 컨테이너와 자식 사이의 제약은 자식을 컨테이너의 뷰 계층 구조에 추가한 후에 설정해라.
Removing a Child View Controller
컨텐츠에서 자식 뷰 컨트롤러를 제거하기 위해서는 다음과 같은 절차를 거친다.
- 자식의
willMoveToParentViewController:
메소드를nil
값과 함께 호출한다. - 자식의 루트 뷰를 구성하는 모든 제약조건을 제거한다.
- 컨테이너의 뷰 계층 구조에서 자식의 루트 뷰를 제거한다.
- 자식의
removeFromParentViewController
메소드를 호출하여 마무리한다.
Suggestions for Building a Container View Controller
컨테이너 클래스를 실행할 때는 다음의 팁을 고려해라.
- 오직 자식 뷰 컨트롤러의 루트 뷰에만 접근해라. 컨테이너는 자식의 루트 뷰만 접근해야 한다. 즉 자식의
view
프로퍼티에서 반환되는 뷰에만 접근해야 한다. - 자식 뷰 컨트롤러는 자신의 컨테이너에 대한 최소한의 정보만 가져야 한다. 자식 뷰 컨트롤러는 자신의 컨텐츠에만 포커스를 맞춰야한다. 컨테이너의 동작을 자식이 영향을 주려면 둘 사이의 상호작용을 관리하기 위해서 delegation을 사용해야만 한다.
- 컨테이너의 표준(regular) 뷰를 먼저 설계해라. 자식 뷰 컨트롤러의 뷰 대신 표준 뷰를 사용하면 레이아웃 제약조건과 애니메이션 전환을 간단한 환경에서 테스트할 수 있다. 표준 뷰가 정확히 동작하면, 자식 뷰 컨트롤러의 뷰로 바꾸면 된다.
Delegating Control to a Child View Controller
컨테이너 뷰 컨트롤러는 자신의 모습(appearance)과 관련한 몇몇을 자식에게 위임(delegate)할 수 있다.
- 자식 뷰 컨트롤러가 상태 바(status bar)를 결정하도록 한다. 상태 바의 형태를 자식에게 위임하기 위해서,컨테이너 뷰 컨트롤러에서
childViewControllerForStatusBarStyle
,childViewControllerForStatusBarHidden
메소드를 재정의(override)해라. - 자식이 자신의 크기를 결정할 수 있도록 한다. 컨테이너는 자식의
preferredContentSize
프로퍼티를 사용하여 자식의 크기를 결정하는 것을 도와줄 수 있다.
Reference
View Controller Programming Guide for iOS - View Controller Definition