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()
}
}
}