Skip to content

Instantly share code, notes, and snippets.

@atierian
Created October 28, 2021 14:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save atierian/fa8194be34c473c48350e50ea6e52d9a to your computer and use it in GitHub Desktop.
Save atierian/fa8194be34c473c48350e50ea6e52d9a to your computer and use it in GitHub Desktop.
Oversimplified Example of MVVM
class MyCell: UITableViewCell {
let titleLabel = UILabel()
let subtitleLabel = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) { nil }
func configure(with cellModel: MyTableViewCellModel) {
titleLabel.text = cellModel.title
subtitleLabel.text = cellModel.subtitle
accessoryType = cellModel.accessoryType
}
}
struct MyTableViewCellModel {
let title: String
let subtitle: String
let accessoryType: UITableViewCell.AccessoryType
}
class MyTableViewDataSource: NSObject, UITableViewDataSource {
let viewModel: MyViewModel
init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
viewModel.dataSet.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell") as! MyCell
let cellModel = viewModel.dataSet[indexPath.row]
cell.configure(with: cellModel)
return cell
}
}
class MyTableViewDelegate: NSObject, UITableViewDelegate {
let viewModel: MyViewModel
init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
viewModel.itemSelected(at: indexPath)
}
}
class MyTextFieldDelegate: NSObject, UITextFieldDelegate {
let viewModel: MyViewModel
init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
func textFieldDidBeginEditing(_ textField: UITextField) {
// viewModel.whatever()
}
}
class MyViewController: UIViewController {
let tableView = UITableView()
let textField = UITextField()
let viewModel: MyViewModel
let tableViewDelegate: MyTableViewDelegate
let tableViewDataSource: MyTableViewDataSource
let textFieldDelegate: MyTextFieldDelegate
init(viewModel: MyViewModel) {
self.viewModel = viewModel
tableViewDelegate = MyTableViewDelegate(viewModel: viewModel)
tableViewDataSource = MyTableViewDataSource(viewModel: viewModel)
textFieldDelegate = MyTextFieldDelegate(viewModel: viewModel)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { nil }
override func viewDidLoad() {
super.viewDidLoad()
// layout
textField.delegate = textFieldDelegate
tableView.delegate = tableViewDelegate
tableView.dataSource = tableViewDataSource
// register cell
}
}
class MyViewModel {
private let service: SomeService
private(set) var dataSet = [MyTableViewCellModel]()
init(service: SomeService) {
self.service = service
}
func search(for text: String) {
service.get(text: text) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let response):
self.dataSet = self.transform(response: response)
case .failure(let error):
print(error) // handle error
}
}
}
private func transform(response: [Response]) -> [MyTableViewCellModel] {
response.compactMap {
let components = $0.value.split(separator: "/").map(String.init)
guard
let title = components.first,
let subtitle = components.last
else { return nil }
let accessoryType: UITableViewCell.AccessoryType = $0.completed ? .checkmark : .none
return .init(title: title, subtitle: subtitle, accessoryType: accessoryType)
}
}
func itemSelected(at indexPath: IndexPath) {
// handle selection
}
}
struct Response {
let completed: Bool
let value: String
}
protocol SomeService {
func get(text: String, completion: (Result<[Response], Error>) -> Void)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment