Issue #37

I like to write UI in code, and with Auto Layout, it is an easy task. However that leaves ViewController with a lots of code. One way we can do is to separate V from C in MVC, by using a dedicated view

We can do that with generic, that initialises a view and replace the view, let’s call it root

import UIKit

class BaseController<T: UIView>: UIViewController {
  let root = T()

  override func loadView() {
    view = root
  }
}

Now we can have a UIView subclass, like LoginView

final class LoginView: UIView {
 lazy var textField: UITextField = UITextField().then {
    $0.textAlignment = .center
    $0.borderStyle = .roundedRect
    $0.keyboardType = .phonePad
  }

  lazy var button: UIButton = UIButton().then {
    $0.setTitleColor(.black, for: .normal)
    $0.backgroundColor = .lightGray
  }

  override init(frame: CGRect) {
    super.init(frame: frame)

    addSubviews(
      textField,
      button
    )

    Constraint.on(
      textField.centerXAnchor.constraint(equalTo: textField.superview!.centerXAnchor),
      textField.centerYAnchor.constraint(equalTo: textField.superview!.centerYAnchor),
      textField.widthAnchor.constraint(equalTo: textField.superview!.widthAnchor, constant: -20),

      button.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20),
      button.centerXAnchor.constraint(equalTo: button.superview!.centerXAnchor),
      button.widthAnchor.constraint(equalTo: textField.widthAnchor, multiplier: 0.8),
      button.heightAnchor.constraint(equalToConstant: 44)
    )
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError()
  }
}

And then the LoginController

final class LoginController: BaseController<LoginView> {
  override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white

    let gr = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
    root.addGestureRecognizer(gr)

    root.button.setTitle("Login", for: .normal)
    root.button.addTarget(self, action: #selector(loginButtonTouched), for: .touchUpInside)
    root.button.isEnabled = false
    root.button.showsTouchWhenHighlighted = true

    root.textField.placeholder = "Phone number"
    root.textField.delegate = self
    root.textField.text = dependencyContainer.phoneService.prefix
    root.textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
  }
}

And this is how we declare the LoginController

let loginController = LoginController()
navigationController.viewControllers = [loginController]