Last active
June 9, 2020 21:10
-
-
Save DhavalDobariya86/911a398a7d09f0dca8c738745ac83c85 to your computer and use it in GitHub Desktop.
MVVM-C View(Controller)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
typealias CountryListViewModelProtocol = CountryListDatasource & ViewModel & Searchable | |
protocol CountryListDatasource { | |
var screenTitle: String { get } | |
var numberOfSections: Int { get } | |
func numberOfRows(in section: Int) -> Int | |
func itemForRow(at indexPath: IndexPath) -> CountryListItemRepresentable | |
func country(at indexPath: IndexPath) -> Country? | |
} | |
protocol CountryListItemRepresentable { | |
var name: String { get } | |
var capital: String { get } | |
} | |
protocol CountryListViewControllerDelegate: class { | |
func didSelect(country: Country, in viewController: UIViewController) | |
} | |
final class CountryListViewController: UIViewController, LoadingDisplayable { | |
private enum Identifier { | |
static let cell = "CellIdentifier" | |
} | |
let loadingViewController = LoadingViewController() | |
weak var delegate: CountryListViewControllerDelegate? | |
private var viewModel: CountryListViewModelProtocol! | |
@IBOutlet private weak var tableView: UITableView! | |
@IBOutlet private weak var searchBar: UISearchBar! | |
// MARK: - View Lifecycle | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
assert(viewModel != nil, "ViewModel for CountryListViewController can not be nil") | |
setupUI() | |
reloadData() | |
} | |
// MARK: - Internal methods | |
func configure(viewModel: CountryListViewModelProtocol) { | |
self.viewModel = viewModel | |
self.viewModel.didUpdate = reloadData | |
self.viewModel.didChangeState = showLoadingIndicator | |
} | |
// MARK: - Private methods | |
private func setupUI() { | |
title = viewModel.screenTitle | |
searchBar.becomeFirstResponder() | |
} | |
private func reloadData() -> Void { | |
tableView.reloadData() | |
} | |
private func showLoadingIndicator(isLoading: Bool, loadingMessage: String?) { | |
guard isLoading else { | |
hideLoading() | |
return | |
} | |
showLoading(with: loadingMessage) | |
} | |
} | |
// MARK: - TableView methods | |
extension CountryListViewController: UITableViewDelegate, UITableViewDataSource { | |
func numberOfSections(in tableView: UITableView) -> Int { | |
viewModel.numberOfSections | |
} | |
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
viewModel.numberOfRows(in: section) | |
} | |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCell(withIdentifier: Identifier.cell, for: indexPath) | |
cell.textLabel?.numberOfLines = 0 | |
cell.detailTextLabel?.numberOfLines = 0 | |
let countryListItemViewModel = viewModel.itemForRow(at: indexPath) | |
cell.textLabel?.text = countryListItemViewModel.name | |
cell.detailTextLabel?.text = countryListItemViewModel.capital | |
return cell | |
} | |
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
tableView.deselectRow(at: indexPath, animated: true) | |
guard let country = viewModel.country(at: indexPath) else { return } | |
delegate?.didSelect(country: country, in: self) | |
} | |
} | |
extension CountryListViewController: UISearchBarDelegate { | |
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { | |
searchBar.resignFirstResponder() | |
guard let searchString = searchBar.text, | |
!searchString.isEmpty else { | |
return | |
} | |
viewModel.searchFor(keyword: searchString) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment