@@ -3,6 +3,9 @@ import UIKit
33/// The view model protocol for filtering a list of models with generic filters.
44///
55protocol FilterListViewModel {
6+ /// The type of the final value returned to the caller of `FilterListViewController`.
7+ associatedtype Criteria
8+
69 // Filter Action UI configuration
710
811 /// The title of the Filter CTA at the bottom.
@@ -14,13 +17,10 @@ protocol FilterListViewModel {
1417 /// Tapping on each filter type row navigates to another list selector for the filter value.
1518 var filterTypeViewModels : [ FilterTypeViewModel ] { get }
1619
17- // Navigation & Actions
18-
19- /// Called when the user taps on the CTA to filter the list with the latest filters.
20- func onFilterActionTapped( )
20+ /// The final value returned to the caller of `FilterListViewController`.
21+ var criteria : Criteria { get }
2122
22- /// Called when the user dismisses the filter list screen.
23- func onDismissActionTapped( )
23+ // Navigation & Actions
2424
2525 /// Called when the user taps on the CTA to clear all filters.
2626 func onClearAllActionTapped( )
@@ -76,12 +76,12 @@ protocol FilterType {
7676/// The UI consists of a list of filters at the top and a Filter CTA at the bottom that is always visible to apply the filters.
7777/// Tapping on a filter in the list navigates to a list of options for the filter.
7878///
79- final class FilterListViewController : UIViewController {
79+ final class FilterListViewController < ViewModel : FilterListViewModel > : UIViewController {
8080
8181 @IBOutlet private weak var navigationControllerContainerView : UIView !
8282 @IBOutlet private weak var filterActionContainerView : UIView !
8383
84- private let viewModel : FilterListViewModel
84+ private let viewModel : ViewModel
8585 private let listSelectorCommand : FilterListSelectorCommand
8686
8787 private lazy var listSelector : ListSelectorViewController
@@ -94,8 +94,21 @@ final class FilterListViewController: UIViewController {
9494 private var cancellableSelectedFilterType : ObservationToken ?
9595 private var cancellableSelectedFilterValue : ObservationToken ?
9696
97- init ( viewModel: FilterListViewModel ) {
97+ private let onFilterAction : ( ViewModel . Criteria ) -> Void
98+
99+ // Strings.
100+
101+ private let navigationBarTitleWithoutActiveFilters =
102+ NSLocalizedString ( " Filters " , comment: " Navigation bar title format for filtering a list of products without filters applied. " )
103+ private let navigationBarTitleFormatWithActiveFilters =
104+ NSLocalizedString ( " Filters (%ld) " , comment: " Navigation bar title format for filtering a list of products with filters applied. " )
105+
106+ /// - Parameters:
107+ /// - viewModel: Used to render the filter list selector and the selected filter value list selector.
108+ /// - onFilterAction: Called when the user taps on the Filter CTA.
109+ init ( viewModel: ViewModel , onFilterAction: @escaping ( ViewModel . Criteria ) -> Void ) {
98110 self . viewModel = viewModel
111+ self . onFilterAction = onFilterAction
99112 self . listSelectorCommand = FilterListSelectorCommand ( data: viewModel. filterTypeViewModels)
100113 super. init ( nibName: " FilterListViewController " , bundle: nil )
101114 }
@@ -123,11 +136,17 @@ final class FilterListViewController: UIViewController {
123136 // MARK: - Navigation
124137 //
125138 @objc func filterActionButtonTapped( ) {
126- viewModel. onFilterActionTapped ( )
139+ dismiss ( animated: true ) { [ weak self] in
140+ guard let self = self else {
141+ return
142+ }
143+ let criteria = self . viewModel. criteria
144+ self . onFilterAction ( criteria)
145+ }
127146 }
128147
129148 @objc func dismissButtonTapped( ) {
130- viewModel . onDismissActionTapped ( )
149+ dismiss ( animated : true ) { }
131150 }
132151
133152 @objc func clearAllButtonTapped( ) {
@@ -224,20 +243,13 @@ private extension FilterListViewController {
224243
225244 func updateListSelectorNavigationTitle( numberOfActiveFilters: Int ) {
226245 listSelectorCommand. navigationBarTitle = numberOfActiveFilters > 0 ?
227- String . localizedStringWithFormat ( Strings . navigationBarTitleFormatWithActiveFilters, numberOfActiveFilters) :
228- Strings . navigationBarTitleWithoutActiveFilters
246+ String . localizedStringWithFormat ( navigationBarTitleFormatWithActiveFilters, numberOfActiveFilters) :
247+ navigationBarTitleWithoutActiveFilters
229248 }
230249
231250 func updateClearAllActionVisibility( numberOfActiveFilters: Int ) {
232251 listSelector. navigationItem. rightBarButtonItem = numberOfActiveFilters > 0 ? clearAllBarButtonItem: nil
233252 }
234-
235- enum Strings {
236- static let navigationBarTitleWithoutActiveFilters =
237- NSLocalizedString ( " Filters " , comment: " Navigation bar title format for filtering a list of products without filters applied. " )
238- static let navigationBarTitleFormatWithActiveFilters =
239- NSLocalizedString ( " Filters (%ld) " , comment: " Navigation bar title format for filtering a list of products with filters applied. " )
240- }
241253}
242254
243255private extension FilterListViewController {
0 commit comments