MVVM + RxSwift 이해하기 쉬운 예제
MVVM + KVO 이해하기 쉬운 예제
위 예제와 동일한 아주 간단한 mvvm + combine 예제이다.
쉬운 예제부터 이해하면 왜 사용하는지를 알고 왜 사용하는지를 알면
코드를 분리하고 유지보수하기 쉬운 코드를 작성하려고 노력하고 좀 더 발전된 방향으로…
View 에서는 viewModel의 label 을 구독하여 갱신이 필요한 시점에서 뷰의 label을 갱신한다.
ViewModel 에서는 View의 label 갱신을 위해 필요한 작업 이후 변경 사항을 저장하여 알린다.
// ViewController class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. if let v: View = UIView.loadFromNib() { v.add(self.view) } } }
// View class View: UIView { @IBOutlet var label: UILabel! private let viewModel = ViewModel() private var cancellables = Set<AnyCancellable>() override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func awakeFromNib() { super.awakeFromNib() // 스케쥴러 main viewModel.$label.receive(on: DispatchQueue.main).sink { [weak self] val in guard let self = self else { return } self.label.text = val }.store(in: &cancellables) viewModel.loadLabel() } func add(_ superView: UIView) { superView.addSubview(self) self.translatesAutoresizingMaskIntoConstraints = false var constraints = [NSLayoutConstraint]() constraints.append(superView.topAnchor.constraint(equalTo: self.topAnchor)) constraints.append(superView.leadingAnchor.constraint(equalTo: self.leadingAnchor)) constraints.append(superView.trailingAnchor.constraint(equalTo: self.trailingAnchor)) constraints.append(superView.bottomAnchor.constraint(equalTo: self.bottomAnchor)) NSLayoutConstraint.activate(constraints) } } extension UIView { class func loadFromNib<T>() -> T? { let identifier = String(describing: T.self) let view = Bundle.main.loadNibNamed(identifier, owner: self, options: nil)?.first return view as? T } }
// Model struct Model { var label: String = "model" }
// ViewModel class ViewModel { private var m = Model() @Published var label = "init" init() { } func changed() { self.label = self.m.label } func loadLabel() { DispatchQueue.global().asyncAfter(deadline: .now()+2) { self.m.label = "value from server or app db" self.changed() } } }