한국어를 찾으세요? 여기를 누르세요
ScenePivot
pattern allows you to get rid of long and complicated UIViewController
creation, configuration, presentation and dismissal from your UIViewController
subclass implementation by abstracting the details behind a data type, SceneRequest
and ScenePivot
.
Creating, Configuring, Presenting and Dismissing a UIViewController
Let’s take a look at a code snippet from the famous sample code: Browsing and Modifying Photo Albums before refactoring it with ScenePivot.
addAlbum(_:)
basically does the following two things:
- Create and present
UIAlertController
with a Text Field - Creates a new Album with the entered text as title by calling
PHPhotoLibrary.performChanges()
And let’s see how we can abstract the UIAlertController
part.
ScenePivot and TextInputRequest
By planting a ScenePivot to MasterViewController
and passing a TextInputRequest
to ScenePivot
we can drastically simplify addAlbum(_:)
like below.
ViewControllerScenePivot
is a concrete type conforms ScenePivot
and passing self as UIViewController
allows it to invoke present(:animted:completion:) to make actual presentation happen
pivot = ViewControllerScenePivot(viewController: self)
Creating TextInputRequest
with a completion handler and sending it to ScenPivot
is all it takes to present UIAlertController
and take entered title
.
let request = TextInputRequest(.newAlbum) {...}
pivot.switchScene(with: request)
Album creation part has been extracted to createNewAlbum(title:)
.
With ScenePivot and SceneRequest in place,
- The presenting View Controller does not need to know the details of how the new View Controller is created and presented
- It is hidden behind
ScenePivot
andSceneRequest
SceneRequest
is only simple data structure represents dependencies and values the newScene
, based onUIViewController
, requires- By hiding and abstracting the details, we can focus on implementing and debugging the View Controller’s own role: Rendering and Layout
By applying this pattern, we’ve experienced identifying more than another 20 View Controller transition take place and thousands of lines of code has been relocated or deleted.
Let’s take a short review on example implementation of ScenePivot
before checking out what needs to be implemented behind TextInputRequest
.
Example Implementation of ScenePivot API
Here is a simplified version of ScenePivot
for demo purpose. The actual version used in the project I’m working on has more types and interfaces but has still not much of code. That’s because most of work is done by implementation that conforms ViewControllerScene
.
A client simply create and send a SceneRequest
to ScenePivot
for transitioning to the next Scene. UIViewController
subclasses or associated logic controllers are typical examples of clients.
ScenePivot
asks SceneBuilder
to create a ViewControllerScene
from SceneRequest
. That part is not included in the code snippet above, and ScenePivot
asks SceneRequest
to directly create ViewControllerScene
for simplicity of demo.
Finally, the created Scene
is asked to perform the actual presentation.
scene.present(from: viewController)
Back State: Behind TextInputRequest
Let’s take a look what needs to be done more in order for the code above to run.
struct TextInputRequest: SceneRequest
is only a simple data type without any functionality. ViewControllerScene
is responsible for presenting a scene and created by ViewControllerScceneBuildable
from SceneRequest
.
Hence, ViewControllerScene implements present(from:)
that creates and presents UIAlertController
.
Pushing to UINavigationController
is also possible in addition to UIViewController.present(:animted:completion:).
UIStoryboardSegue
based transition can also be implemented with some limitation. Let’s hope for another chance to talk about it.
About TextInput(.newAlbum)
By adding TextInputRequest.InputType.newAlbum
, we could simplify creation even further: TextInputRequest(.newAlbum)
.
It was possible because NSLocalizedString()
parts have been separated from UIAlertController construction.
Summary
- Transitioning to another
UIViewController
can be far more complicated than we think - How many possible different
UIViewController
transitions from a View Controller are there in the project you are working on? SceneRequest
represents dependencies and data for the nextScene
- Scene transition is expressed as sending a
SceneRequest
toScenePivot
- It’s
ViewControllerScene
’s responsibility to create and present UIViewController and it takesSceneRequest
andUIViewController
as input ScenePivot
is rather a pattern than a framework. You may end up adopting it with a much improved version of implementation.