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]