Skip to content

Instantly share code, notes, and snippets.

@DhavalDobariya86
Last active June 9, 2020 21:10
Show Gist options
  • Save DhavalDobariya86/911a398a7d09f0dca8c738745ac83c85 to your computer and use it in GitHub Desktop.
Save DhavalDobariya86/911a398a7d09f0dca8c738745ac83c85 to your computer and use it in GitHub Desktop.
MVVM-C View(Controller)
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