Displaying and Managing Views with a View Controller

Panther·2021년 8월 20일
0

https://developer.apple.com/documentation/uikit/view_controllers/displaying_and_managing_views_with_a_view_controller

"Build a view controller in storyboards, configure it with custom views, and fill those views with your app’s data."

스토리보드에 뷰 컨트롤러를 빌드하고, 커스텀 뷰와 함께 설정하며, 앱 데이터로 해당 뷰를 채웁니다.

Overview

MVC 디자인 패러다임에서 뷰 컨트롤러는 정보를 화면에 나타내는 뷰 객체와 앱 컨텐트를 저장하는 데이터 객체 사이를 맞춥니다. 구체적으로 뷰 컨트롤러는 뷰 계층구조와 뷰를 최신으로 유지하기 위해 필요한 상태 정보를 관리합니다. 모든 UIKit 앱은 컨텐트를 나타내기 위해 뷰 컨트롤러에 강하게 의존하며, 뷰와 UI 관련 로직을 관리하기 위해 커스텀 뷰 컨트롤러를 정의하게 될 것입니다.

생성하는 대부분의 커스텀 뷰 컨트롤러는 컨텐트 뷰 컨트롤러일 것입니다(즉 뷰 컨트롤러가 자신의 모든 뷰를 갖고 있고, 해당 뷰에 대한 상호작용을 관리합니다). 앱의 커스텀 컨텐트를 화면에 나타내기 위해 컨텐트 뷰 컨트롤러를 사용할 수 있으며, 커스텀 뷰로 데이터를 전달하거나 커스텀뷰로부터 데이터를 전달받는 데이터 전달 관리를 위해 뷰 컨트롤러 객체를 사용할 수 있습니다.

Note
컨텐트 뷰 컨트롤러와 반대로 컨테이너 뷰 컨트롤러는 다른 뷰 컨트롤러로부터 컨텐트를 뷰 계층구조로 통합합니다. UINavigationController가 컨테이너 뷰 컨트롤러의 예시입니다. 컨테이너 뷰 컨트롤러 구현 방법에 대한 정보는 Implementing a Custom Container View Controller를 보시기 바랍니다.

Implementing a Custom Container View Controller
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html#//apple_ref/doc/uid/TP40007457-CH11-SW12
https://velog.io/@panther222128/View-Controller-Definition#implementing-a-container-view-controller

컨텐트 뷰 컨트롤러를 정의하려면 UIViewController 서브클래싱부터 시작합니다. 인터페이스가 테이블 뷰 홋은 컬렉션 뷰를 포함하고 있다면 대신 UITableViewController 혹은 UICollectionViewController를 서브클래싱 해야 합니다. 새 Xcode 프로젝트는 하나 혹은 하나 이상의 컨텐트 뷰 컨트롤러를 포함하고 있습니다. 수정이 가능하며 다른 무언가를 추가할 수 있습니다.

Add Views to Your View Controller

UIViewController는 뷰 계층구조의 루트 뷰 역할을 한느 뷰 속성으로부터 접근 가능한 컨텐트 뷰를 포함합니다. 해당 루트 뷰로 인터페이스를 나타내기에 필요한 커스텀 뷰를 추가할 수 있습니다. 스토리보드에서 뷰 컨트롤러 씬으로 커스텀 뷰를 드래그해서 뷰를 추가할 수 있습니다. 예를 들어 아래 그림은 아이폰에서 이미지 뷰와 버튼을 갖는 뷰 컨트롤러를 보여줍니다.

뷰 컨트롤러에 뷰를 추가한 후 항상 해당 뷰의 크기 및 위치를 설정하기 위해 오토 레이아웃 제약을 추가해야 합니다. 제약은 뷰의 부모 혹은 형제뷰에 상대적인 크기 및 위치를 어떻게 할지 구체화하는 규칙이며, 제약은 다른 환경 및 기기에 자동으로 뷰가 적응할 수 있도록 해줍니다. 더 많은 정보는 View Layout을 보시기 바랍니다.

View Layout
https://developer.apple.com/documentation/uikit/view_layout

Store References to Important Views

런타임 시점에 뷰 컨트롤러의 코드로부터 뷰에 접근할 필요가 있을 것입니다. 예를 들어 텍스트 뷰에서 텍스트를 가져오길 원할 수도 있고, 이미지 뷰에서 이미지를 변경시키길 원할 수도 있습니다. 이렇게 하려면 뷰 계층구조에서 뷰에 대한 참조가 필요합니다. 이러한 참조는 아웃렛을 사용해서 생성할 수 있습니다.

아웃렛은 IBOutlet 키워드를 포함하는, 뷰 컨트롤러에 있는 속성입니다. 이 키워드의 존재는 Xcode가 스토리보드에서 해당 속성을 드러낼 것을 알려줍니다. 아래 예시 코드는 두 가지 아웃렛에 대한 정의를 보여주고 있습니다. 스위프트에서 뷰 컨트롤러가 뷰에 두 번째 강한 참조를 갖지 않도록 weak 케워드를 포함시켜야 합니다(첫 번째는 뷰 계층구조 자신으로부터 기인합니다).

@IBOutlet weak var imageView : UIImageView?
@IBOutlet weak var button : UIButton?

Add an outlet connection to send a message to a UI object에서 설명하는 것처럼 스토리보드에서 각 아웃렛을 상응하는 뷰에 연결시켜야 합니다. 뷰 계층구조에서 모든 뷰에 대한 참조를 저장할 필요는 없습니다. 이후에 수정하게 될 뷰에 대한 참조만 저장하시기 바랍니다.

Add an outlet connection to send a message to a UI object
https://help.apple.com/xcode/mac/current/#/devc06f7ee11

뷰 컨트롤러를 인스턴스화 할 때 UIKit은 스토리보드에서 설정한 모든 아웃렛을 재연결합니다. UIKit은 뷰 컨트롤러의 viewDidLoad() 메소드 호출 전에 이러한 연결을 다시 설정합니다. 그렇기 때문에 이 메소드에서 해당 속성의 객체에 접근할 수 있습니다. 뷰를 코드 작성으로 생성하는 경우 뷰 컨트롤러의 적합한 속성에 명시적으로 뷰를 할당해줘야 합니다.

Handle Events Occurring in Views and Controls

컨트롤은 사용자 상호작용을 알리기 위해 타깃 액션 디자인 패턴을 사용하며, 몇 가지 뷰는 변경사항에 대한 응답으로 노티피케이션을 포스트하거나 딜리게이트 메소드를 호출합니다. 뷰 컨트롤러는 이러한 상호작용에 대해 알아야 할 필요가 있으며, 이를 통해 뷰를 업데이트 합니다. 그리고 이렇게 할 수 잇는 몇 가지 방법이 있습니다.

  • 뷰 컨트롤러에서 딜리게이트 및 액션 메소드를 구현합니다. 이 옵션은 구현하기에 간단하고 쉽지만 유연성이 떨어지고 코드에 대한 테스트와 유효성 검증을 어렵게 합니다.
  • 뷰 컨트롤러에서 클래스 확장에 딜리게이트 및 메소드를 구현합니다. 이 옵션은 이벤트 처리 코드와 뷰 컨트롤러의 나머지를 분리합니다. 이로써 코드에 대한 테스트 및 유효성 검증이 더 쉬워집니다.
  • 이후에 뷰 컨트롤러로 관련 정보를 전달하는 전용 객체에 딜리게이트 및 액션 메소드를 구현합니다. 이 옵션은 가장 높은 수준의 유연성과 재사용성을 제공합니다. 또한, 책임의 분리는 단위 테스트 작성을 더 쉽게 만들어줍니다.

컨트롤에 대한 사용자 상호작용에 응답하려면 아래 코드 리스트에서 보이는 시그니처 중 한 가지와 함께 액션 메소드를 정의해야 합니다. 메소드 정의에서 UIControl에 대한 제너릭 레퍼런스를 더 구체적인 컨트롤 클래스로 교체하면 됩니다.

@IBAction func doSomething()
@IBAction func doSomething(sender: UIControl)
@IBAction func doSomething(sender: UIControl, forEvent event: UIEvent)

타깃 액션 디자인 패턴과 컨트롤 관련 이벤트 처리 방법에 대한 더 많은 정보는 UIControl을 보시기 바랍니다.

UIControl
https://developer.apple.com/documentation/uikit/uicontrol
https://velog.io/@panther222128/UIControl

Prepare Your Views to Appear Onscreen

UIKit은 뷰를 화면에 표시하기 전에 뷰 컨트롤러 및 뷰를 설정할 수 있는 몇 가지 기회를 줍니다. 스토리보드로부터 뷰 컨트롤러를 인스턴스화 할 때 UIKit은 이 객체의 init(coder:) 메소를 호출해서 객체를 생성합니다.

Note
뷰 컨트롤러의 커스텀 초기화가 코더 객체가 제공할 수 있는 것을 넘어서면 UIStoryboardinstantiateInitialViewController(creator:) 메소드를 사용해서 코드 작성을 통해 이를 인스턴스화할 수 있습니다. 이 메소드는 블록과 UIKit이 제공하는 코더 객체를 사용해 뷰 컨트롤러를 직접 생성할 수 있게 해줍니다. 이 옵션은 뷰 컨트롤러가 요구하는 커스텀 데이터를 갖는 뷰 컨트롤러 초기화를 가능하게 하고, 스토리보드에서 뷰 및 다른 객체의 설정을 복구할 수도 있습니다.

뷰 컨트롤러를 화면에 나타낼 때 UIKit은 처음으로 로드하고, 아래 단계의 연속을 사용하는 뷰를 설정합니다.

  1. 뷰의 init(coder:) 메소드를 사용해서 각 뷰를 생성합니다.
  2. 뷰 컨트롤러에서 뷰와 뷰에 상응하는 액션 및 아웃렛을 연결합니다.
  3. 각각의 뷰와 뷰 컨트롤러의 awakeFromNib() 메소드를 호출합니다.
  4. 뷰 계층구조를 뷰 컨트롤러의 뷰 속성에 할당합니다.
  5. 뷰 컨트롤러의 viewDidLoad() 메소드를 호출합니다.

로드 시점에 뷰 컨트롤러 준비에 필요한 one-time 설정 단계만을 수행합니다. 스토리보드의 부분이 아닌 추가적인 뷰를 생성하고 설정하려면 로드 타임을 사용하시기 바랍니다. 뷰 컨트롤러가 스크린에 나타날 때마다 발생해야 하는 작업을 수행하지 않아야 합니다. 예를 들어 애니메이션을 시작하거나 뷰의 값을 업데이트하지 않아야 합니다.

뷰가 스크린에 나타나기 전에 모든 마지막 뷰 관련 작업을 짧게 수행해야 합니다. UIKit은 뷰가 스크린에 나타날 준비가 되었을 때 가지고 있는 뷰 컨트롤러에게 알리고, 현재 환경에 맞추기 위해 해당하는 뷰의 레이아웃을 업데이트합니다. 아래 메소드를 순서대로 호출하면서 이뤄집니다.

  1. 타깃 윈도우에 기반해 뷰 컨트롤러의 특성 컬렉션을 업데이트합니다.
  2. 뷰 컨트롤러의 뷰가 스크린에 나타날 준비가 되었다는 것을 알 수 있도록 viewWillAppear(_:) 메소드를 호출합니다.
  3. 필요한 경우 현재 레이아웃 마진을 업데이트 하고 viewLayoutMarginsDidChange() 메소드를 호출합니다.
  4. 필요한 경우 safe area inset을 업데이트 하고 viewSafeAreaInsetsDidChange() 메소드를 호출합니다.
  5. viewWillLayoutSubviews() 메소드를 호출합니다.
  6. 뷰 계층구조의 레이아웃을 업데이트합니다.
  7. viewDidLayoutSubviews() 메소드를 호출합니다.
  8. 뷰를 스크린에 표시합니다.
  9. 뷰 컨트롤러의 viewDidAppear(_:) 메소드를 호출합니다.

뷰 컨트롤러의 viewWillAppear(_:) 메소드에서 뷰의 컨텐트를 업데이트할 수 있습니다. 여러 뷰의 컨텐트를 변경하는 것은 자동 레이아웃 업데이트를 트리거합니다. 그렇기 때문에 이 메소드에 변경사항을 만드는 것은 추가적인 레이아웃 단계를 피합니다. 변경사항을 만들 때 현재 환경에 대한 정보(디스플레이 스케일 혹은 수평과 수직 사이즈 클래스와 같은)에 접근하기 위해 뷰 컨트롤러의 traitCollection 속성을 사용할 것입니다. viewWillAppear(_:)보다 빠르게 특성에 접근할 수 있을지라도 특성은 해당 메소드까지 완료될 것이라는 보장은 없습니다. iOS 12 및 이전 버너에서 UIKit은 로드 타임 시점에 특성의 부분 집합만을 제공하며, viewWillAppear(_:) 메소드 전까지 특성으 ㅣ완전한 집합을 제공하지 않습니다. 사용 가능한 특성에 대한 더 많은 정보는 UITraitCollection을 보시기 바랍니다.

UITraitCollection
https://developer.apple.com/documentation/uikit/uitraitcollection
https://velog.io/@panther222128/UITraitCollection

See Also


Content View Controllers

Showing and Hiding View Controllers

다른 테크닉을 사용해서 뷰 컨트롤러를 표시합니다. 그리고 뷰 컨트롤러 사이에 전환이 진행되는 동안 데이터를 전달합니다.

https://developer.apple.com/documentation/uikit/view_controllers/showing_and_hiding_view_controllers
https://velog.io/@panther222128/Showing-and-Hiding-View-Controllers

UIViewController

UIKit 앱의 뷰 계층구조를 관리하는 객체입니다.

https://developer.apple.com/documentation/uikit/uiviewcontroller
https://velog.io/@panther222128/ViewController

UITableViewController

테이블 뷰 관리에 특화된 뷰 컨트롤러입니다.

https://developer.apple.com/documentation/uikit/uitableviewcontroller
https://velog.io/@panther222128/UITableViewController

UICollectionViewController

컬렉션 뷰 관리에 특화된 뷰 컨트롤러입니다.

https://developer.apple.com/documentation/uikit/uicollectionviewcontroller
https://velog.io/@panther222128/UICollectionViewController


0개의 댓글