// // TestViewController.swift // VDSSample // // Created by Matt Bruce on 8/12/22. // import Foundation import UIKit import Combine import VDS struct User { var firstName: String var lastName: String init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName } } class TextFieldBindingCell: UIControl { private let firstNameTextField = TextField() private let lastNameTextField = TextField() private var subscriptions = Set() var user: User { User(firstName: firstNameTextField.text ?? "", lastName: lastNameTextField.text ?? "" ) } init(user: User) { super.init(frame: .zero) firstNameTextField.text = user.firstName lastNameTextField.text = user.lastName translatesAutoresizingMaskIntoConstraints = false firstNameTextField.translatesAutoresizingMaskIntoConstraints = false lastNameTextField.translatesAutoresizingMaskIntoConstraints = false addSubview(firstNameTextField) addSubview(lastNameTextField) firstNameTextField.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true firstNameTextField.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true firstNameTextField.topAnchor.constraint(equalTo: topAnchor).isActive = true firstNameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true lastNameTextField.topAnchor.constraint(equalTo: firstNameTextField.bottomAnchor, constant: 20).isActive = true lastNameTextField.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true lastNameTextField.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true lastNameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true lastNameTextField.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true firstNameTextField .textPublisher .sink { [weak self] _ in self?.sendActions(for: .valueChanged) }.store(in: &subscriptions) lastNameTextField .textPublisher .sink { [weak self] _ in self?.sendActions(for: .valueChanged) }.store(in: &subscriptions) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } @objcMembers class TestViewController: UIViewController, Initable { deinit { print("\(Self.self) deinit") } var user = User(firstName: "Joe", lastName: "User") { didSet { print("User oldValue: \(oldValue)") print("User newValue: \(user)") } } private var subscriptions = Set() required init() { super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white let nameTextField = TextFieldBindingCell(user: user) let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false view.addSubview(nameTextField) view.addSubview(button) nameTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true nameTextField.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true nameTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true button.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true button.topAnchor.constraint(equalTo: nameTextField.bottomAnchor, constant: 20).isActive = true button.heightAnchor.constraint(equalToConstant: 50).isActive = true button.widthAnchor.constraint(equalToConstant: 100).isActive = true button.backgroundColor = .blue button.setTitle("Print", for: .normal) //publishers nameTextField .publisher(for: .valueChanged) .sink(receiveValue: { [weak self] control in guard let self else { return } self.user = control.user }) .store(in: &subscriptions) button .tapPublisher .sink { [weak self] _ in if let user = self?.user { print("\(user.firstName) \(user.lastName)") } }.store(in: &subscriptions) } } class TextField: UITextField { var textPadding = UIEdgeInsets( top: 10, left: 20, bottom: 10, right: 20 ) override func textRect(forBounds bounds: CGRect) -> CGRect { layer.borderColor = UIColor.black.cgColor layer.borderWidth = 1 let rect = super.textRect(forBounds: bounds) return rect.inset(by: textPadding) } override func editingRect(forBounds bounds: CGRect) -> CGRect { layer.borderColor = UIColor.black.cgColor layer.borderWidth = 1 let rect = super.editingRect(forBounds: bounds) return rect.inset(by: textPadding) } }