ScenePivot: Complete Abstraction of View Controller Transition

Simon
3 min readDec 3, 2020

--

Looking for English Version? Follow this link.

복잡한 UIAlertController 생성, 설정, 보여주기, 그리고 닫기

ScenePivot 을 사용하면 이 복잡한 과정을 저 멀리 치워버리고 원래 하려던 일에 집중할 수 있습니다.

사과회사의 유명한 예제를 다운로드 해서 새 사진 앨범 제목을 입력받는 부분을 살펴본 다음, ScenePivot 으로 간소화 해 보기로 합시다.

Browsing and Modifying Photo Albums 에서 새 사진앨범 제목을 입력받는 addAlbum(_:) function:

ScenePivot 과 TextInputRequest로 교체

ScenePivotTextInputRequest 를 사용해서 코드를 고쳐봅시다

Details of building UIAlertController are hidden

ViewControllerScenePivot instance를 만들어 self.pivot property에 넣습니다. 화면전환이 일어날 때 pivotpresent(:animted:completion:) 을 호출할 수 있도록 화면의 UIViewController를 전달합니다.

pivot = ViewControllerScenePivot(viewController: self)

TextInputRequest 를 completion handler 와 함께 만들어 pivot 에서 장면전환을 요청하면 위 화면과 동일한 기능을 수행합니다. 깔끔하죠?

let request = TextInputRequest(.newAlbum) {...}pivot.switchScene(with: request)

새 Album 을 생성하는 부분은 createNewAlbum(title:) 로 분리되었습니다.

ScenePivotSceneRequest 를 사용하면

  • 화면에 새로 보여질 View Controller 를 만들고, 구성하고 보여주고 숨기는 절차를 현재 화면의 View Controller 코드에서 알 필요가 없습니다
  • ScenePivotSceneRequest 이면에 그 자세한 내용을 숨길 수 있습니다
  • 단순 자료구조인 SceneRequest 에 다음 장면 (UIViewController 기반의 Scene) 에서 필요로 하는 의존객체와 값 (Dependency) 만 표현합니다
  • 장면 구성, 표시, 숨기기 절차를 제거함으로써 현재 화면의 View Controller 는 더 간단해지고 원래의 목적인 화면 구성요소 표시에 집중할 수 있습니다

실제 ScenePivot 을 적용한 후에 어떤 화면에서는 총 20개가 넘는 다음장면 전환이 있다는 사실을 알게 됐습니다. 그리고 줄어든 (이 아니라 분리되어 이동한) 코드의 양은 수천줄에 달합니다.

MVVM 이나 VIP 등에서 View 와 뒤섞여 있는 Logic 을 분리하는 장점을 제공한다면 ScenePivot 은 화면전환의 복잡성을 제거하고, 더 나아가 여러가지로 다양한 화면 전환을 손쉽게 시도해서 결과를 빠르게 확인할 수 있는 유연성을 제공하는데 그 목적과 특징이 있습니다.

TextInputRequest 이면을 살펴보기전에 ScenePivot 의 실체를 살짝 확인하도록 하지요.

ScenePivot API 와 구현

데모를 위해 최소한의 코드만 담도록 구현된 ScenePivot 의 간단한 버전을 살펴봅시다. 실제 제가 참여하고 있는 프로젝트에서 사용중인 구현은 이보다 좀 더 많은 Type 과 Interface 가 있지만 여전히 구현된 코드의 양은 많지 않습니다. 실제 동작하는 코드의 대부분은 App 에서 ViewControllerScene 을 conform 하는 부분이기 때문입니다.

Client 는 다음장면에 필요한 Data 를 SceneRequest 에 담아 ScenePivot 에게 장면전환을 요청합니다. Client 는 한 장면을 담당하는 UIViewController 혹은 연결되어 있는 Logic Controller 가 될 수 있습니다.

ScenePivotSceneBuilder 에게 SceneRequest 에 대응하는 ViewControllerScene 을 만들것을 요청합니다. 위 데모코드 에서는 이 부분이 생략되어 있고 SceneRequest 에게 직접 ViewControllerScene 을 만들도록 요청합니다.

마지막으로, 만들어진 Scene 에게 화면표시 하도록 요청합니다

scene.present(from: viewController)

Back Stage: TextInputRequest 의 이면

위의 코드가 동작하려면 TextInputRequest 와 그 이면이 어떻게 구현됐는지 살펴보시죠.

TextInputRequest: SceneRequest는 기능을 수행하지 않는 단순 자료구조 입니다. 장면을 구성하고 화면표시하는 것은 ViewControllerScene 의 역할이기 때문에ViewControllerSceneBuildableTextInputRequest 로 부터 만들어 내는 일을 수행합니다.

만들어진 장면(ViewControllerScene) 은 present(from:) 을 구현해서 실제 화면에 새로운 UIViewController 를 만들어 표시합니다.

present(:animted:completion:) 분만 아니라 UINavigationController 에 push 를 하는 것과 같이 다양한 형태의 장면전환 방법을 모두 사용할 수 있습니다.

Storyboard 기반의 장면전환일 경우 어느정도 제약이 있지만 여전히 가능합니다. (자세한 내용은 다음기회에…)

TextInputRequest(.newAlbum) 처럼 용도를 지정해서 간단하게 호출할 수 있도록 하기 위해서 TextInputRequest.InputType.newAlbum 을 추가 했습니다.

화면의 각 요소에 표시되어야 하는 String을 별도의 Type으로 표현하도록 분리한 덕분에 가능해졌습니다.

Summary

  • 새로운 View Controller 를 만들어 화면을 전환하는것은 생각보다 코드가 복잡할 수 있습니다
  • 지금 참여하신 프로젝트에서 하나의 View Controller 에서 전환되어 표시되는 View Controller 는 많으면 몇 개 까지 가지고 있을까요?
  • 새 화면에 필요한 입력 Data 와 의존성을 SceneRequest 로 표현합니다
  • 장면전환 요청은 ScenePivot에게 SceneRequest를 전달하는 형태로 합니다
  • View Controller 를 만들고 구성해서 화면표시 하는것은 ViewControllerScene 의 역할이며 SceneRequestUIViewController를 입력으로 받습니다
  • ScenePivot은 Framework 이기 보다는 Pattern에 가까우므로 실제 구현될 코드의 양은 적으며 필요에 따라 얼마든지 개선해서 사용하실 수 있습니다

--

--