Swift/UIKit

[UIKit] MVVM 에서 KVO 사용하기

insub4067 2022. 12. 29. 16:15
import UIKit

class ViewController: UIViewController {

    var viewModel = ViewModel()

    let label = UILabel()
    let button = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()
        configure()
        observe()
    }

    func configure() {
        view.backgroundColor = .white

        view.addSubview(label)
        view.addSubview(button)

        label.translatesAutoresizingMaskIntoConstraints = false
        button.translatesAutoresizingMaskIntoConstraints = false

        label.textColor = .gray
        label.font = .systemFont(ofSize: 20)
        label.text = "버튼을 누르세요"


        button.setTitle("버튼", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)

        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
            label.heightAnchor.constraint(equalToConstant: 20),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }

    func observe() {
        viewModel.addObserver(self, forKeyPath: #keyPath(ViewModel.man), options: [.new], context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let man = change?[NSKeyValueChangeKey.newKey] as? Person
        guard let man = man else { return }
        label.text = "\(man.name)님의 나이는 \(man.age)살 입니다"
    }

    @objc func didTapButton() {
        viewModel.fetchData()
    }

}
import Foundation

class ViewModel: NSObject {
    @objc dynamic var man: Person?

    func fetchData() {
        man = Person(name: "Woody", age: 28)
    }
}
import Foundation

class Person: NSObject {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}