@@ -71,10 +71,6 @@ class RootViewController: OpaqueNavigationController {
71
71
fatalError ( " init(coder:) has not been implemented " )
72
72
}
73
73
74
- fileprivate func presentViewController( _ viewController: UIViewController ) {
75
- presentViewControllers ( [ viewController] )
76
- }
77
-
78
74
fileprivate func presentViewControllers( _ viewControllersToPresent: [ UIViewController ] ) {
79
75
// If there is currently no modal, create one.
80
76
guard let navController = modalNavController else {
@@ -101,37 +97,35 @@ class RootViewController: OpaqueNavigationController {
101
97
}
102
98
}
103
99
104
- protocol ModelBasedViewController {
100
+ protocol ModelBased {
105
101
associatedtype ViewModel
106
102
associatedtype Action
107
103
108
104
init ( viewModel: ViewModel , dispatchAction: @escaping ( Action ) -> Void )
109
105
func update( with viewModel: ViewModel )
110
106
}
111
107
112
- extension TokenScannerViewController : ModelBasedViewController { }
113
- extension TokenFormViewController : ModelBasedViewController { }
114
- extension InfoListViewController : ModelBasedViewController { }
115
- extension InfoViewController : ModelBasedViewController { }
116
-
117
- extension RootViewController {
118
- private func reify< ViewController: ModelBasedViewController > ( viewModel: ViewController . ViewModel , dispatchAction: @escaping ( ViewController . Action ) -> Void ) -> ViewController {
119
- return reify ( modalNavController? . topViewController, viewModel: viewModel, dispatchAction: dispatchAction)
120
- }
121
-
122
- private func reify< ViewController: ModelBasedViewController > ( _ existingViewController: UIViewController ? , viewModel: ViewController . ViewModel , dispatchAction: @escaping ( ViewController . Action ) -> Void ) -> ViewController {
123
- if let viewController = existingViewController as? ViewController {
124
- viewController. update ( with: viewModel)
125
- return viewController
126
- } else {
127
- let viewController = ViewController (
128
- viewModel: viewModel,
129
- dispatchAction: dispatchAction
130
- )
131
- return viewController
132
- }
108
+ typealias ModelBasedViewController = UIViewController & ModelBased
109
+
110
+ extension TokenScannerViewController : ModelBased { }
111
+ extension TokenFormViewController : ModelBased { }
112
+ extension InfoListViewController : ModelBased { }
113
+ extension InfoViewController : ModelBased { }
114
+
115
+ private func reify< ViewController: ModelBasedViewController > ( _ existingViewController: UIViewController ? , viewModel: ViewController . ViewModel , dispatchAction: @escaping ( ViewController . Action ) -> Void ) -> ViewController {
116
+ if let viewController = existingViewController as? ViewController {
117
+ viewController. update ( with: viewModel)
118
+ return viewController
119
+ } else {
120
+ let viewController = ViewController (
121
+ viewModel: viewModel,
122
+ dispatchAction: dispatchAction
123
+ )
124
+ return viewController
133
125
}
126
+ }
134
127
128
+ extension RootViewController {
135
129
func update( with viewModel: Root . ViewModel ) {
136
130
tokenListViewController. update ( with: viewModel. tokenList)
137
131
@@ -140,52 +134,62 @@ extension RootViewController {
140
134
dismissViewController ( )
141
135
142
136
case . scanner( let scannerViewModel) :
143
- let scannerViewController : TokenScannerViewController = reify (
144
- viewModel: scannerViewModel,
145
- dispatchAction: compose ( Root . Action. tokenScannerAction, dispatchAction)
146
- )
147
- presentViewController ( scannerViewController)
137
+ presentViewModel ( scannerViewModel,
138
+ using: TokenScannerViewController . self,
139
+ actionTransform: Root . Action. tokenScannerAction)
148
140
149
141
case . entryForm( let formViewModel) :
150
- let formController : TokenFormViewController = reify (
151
- viewModel: formViewModel,
152
- dispatchAction: compose ( Root . Action. tokenEntryFormAction, dispatchAction)
153
- )
154
- presentViewController ( formController)
142
+ presentViewModel ( formViewModel,
143
+ using: TokenFormViewController . self,
144
+ actionTransform: Root . Action. tokenEntryFormAction)
155
145
156
146
case . editForm( let formViewModel) :
157
- let editController : TokenFormViewController = reify (
158
- viewModel: formViewModel,
159
- dispatchAction: compose ( Root . Action. tokenEditFormAction, dispatchAction)
160
- )
161
- presentViewController ( editController)
147
+ presentViewModel ( formViewModel,
148
+ using: TokenFormViewController . self,
149
+ actionTransform: Root . Action. tokenEditFormAction)
162
150
163
151
case let . info( infoListViewModel, infoViewModel) :
164
- updateWithInfoViewModels ( infoListViewModel, infoViewModel)
152
+ if let infoViewModel = infoViewModel {
153
+ presentViewModels ( infoListViewModel,
154
+ using: InfoListViewController . self,
155
+ actionTransform: Root . Action. infoListEffect,
156
+ and: infoViewModel,
157
+ using: InfoViewController . self,
158
+ actionTransform: Root . Action. infoEffect)
159
+
160
+ } else {
161
+ presentViewModel ( infoListViewModel,
162
+ using: InfoListViewController . self,
163
+ actionTransform: Root . Action. infoListEffect)
164
+ }
165
165
}
166
166
currentViewModel = viewModel
167
167
}
168
168
169
- private func updateWithInfoViewModels( _ infoListViewModel: InfoList . ViewModel , _ infoViewModel: Info . ViewModel ? ) {
170
- guard let infoViewModel = infoViewModel else {
171
- let infoListViewController : InfoListViewController = reify (
172
- viewModel: infoListViewModel,
173
- dispatchAction: compose ( Root . Action. infoListEffect, dispatchAction)
174
- )
175
- presentViewController ( infoListViewController)
176
- return
177
- }
169
+ private func presentViewModel< ViewController: ModelBasedViewController > ( _ viewModel: ViewController . ViewModel , using _: ViewController . Type , actionTransform: @escaping ( ( ViewController . Action ) -> Root . Action ) ) {
170
+ let viewController : ViewController = reify (
171
+ modalNavController? . topViewController,
172
+ viewModel: viewModel,
173
+ dispatchAction: compose ( actionTransform, dispatchAction)
174
+ )
175
+ presentViewControllers ( [ viewController] )
176
+ }
178
177
179
- let infoListViewController : InfoListViewController = reify (
178
+ // swiftlint:disable:next function_parameter_count
179
+ private func presentViewModels< A: ModelBasedViewController , B: ModelBasedViewController > (
180
+ _ viewModelA: A . ViewModel , using _: A . Type , actionTransform actionTransformA: @escaping ( ( A . Action ) -> Root . Action ) ,
181
+ and viewModelB: B . ViewModel , using _: B . Type , actionTransform actionTransformB: @escaping ( ( B . Action ) -> Root . Action ) ) {
182
+ let viewControllerA : A = reify (
180
183
modalNavController? . viewControllers. first,
181
- viewModel: infoListViewModel ,
182
- dispatchAction: compose ( Root . Action . infoListEffect , dispatchAction)
184
+ viewModel: viewModelA ,
185
+ dispatchAction: compose ( actionTransformA , dispatchAction)
183
186
)
184
- let infoViewController : InfoViewController = reify (
185
- viewModel: infoViewModel,
186
- dispatchAction: compose ( Root . Action. infoEffect, dispatchAction)
187
+ let viewControllerB : B = reify (
188
+ modalNavController? . topViewController,
189
+ viewModel: viewModelB,
190
+ dispatchAction: compose ( actionTransformB, dispatchAction)
187
191
)
188
- presentViewControllers ( [ infoListViewController , infoViewController ] )
192
+ presentViewControllers ( [ viewControllerA , viewControllerB ] )
189
193
}
190
194
}
191
195
0 commit comments