일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- weak var
- 단일 책임원칙
- Required Reason API
- swift
- CLLocationManagerDelegate
- Startign Assignments
- RunningTimer
- Protocol
- CoreLocation
- Xcode
- UIAlertAction
- WeatherManager
- dispatchsource
- MKMapViewDelegate
- Timer
- xcode로 날씨앱 만들기
- AnyObject
- weatherKit
- 영문 개인정보처리방침
- App Store Connect
- 클로저의 캡슐화
- 한국어 개인정보처리방침
- MKMapItem
- 러닝타이머
- 러닝기록앱
- UICollectionViewFlowLayout
- SwiftUI Boolean 값
- 서체관리자
- font book
- addannotation
- Today
- Total
VesselWheel
MVVM 아키텍처 활용하기 본문
https://vesselwheel.tistory.com/165
MVVM 개념을 알아보았다면, 코드 단에서 어떻게 활용되는지 알아보자.
1. 타입을 지정하기 위한 구조체 생성
import Foundation
struct User {
var name: String
var age: Int
}
- 이름과 나이가 프로퍼티로 지정된 User타입 구조체 생성
2. 다리 역할을 할 ViewModel 생성
import Foundation
protocol UserViewModelDelegate: AnyObject {
func updateUserName(name: String)
func updateUserAge(age: Int)
}
class UserViewModel {
private var user: User // User 타입의 user 프로퍼티 생성
weak var delegate: UserViewModelDelegate? // delegate pattern 활용
init(user: User, delegate: UserViewModelDelegate? = nil) {
self.user = user
self.delegate = delegate
}
lazy var userName: String = user.name {
didSet {
delegate?.updateUserName(name: userName)
}
}
lazy var userAge: Int = user.age {
didSet {
delegate?.updateUserAge(age: userAge)
}
}
}
3. 사용자에게 보여지는 UI 부분인 View 생성(xcode는 ViewController가 View와 Controller의 역할을 함께 한다.)
//
// MVVMViewController.swift
// Instagram
//
// Created by Jason Yang on 2/3/24.
//
import UIKit
import SnapKit
class MVVMViewController: UIViewController {
lazy var nameLabel: UILabel = {
let label = UILabel()
label.textColor = .blue
return label
}()
lazy var ageLabel: UILabel = {
let label = UILabel()
return label
}()
lazy var button: UIButton = {
let button = UIButton()
button.setTitle("random age", for: .normal)
button.setTitleColor(.gray, for: .normal)
button.addTarget(self, action: #selector(changeAge), for: .touchUpInside)
return button
}()
//viewModel 프로퍼티 생성
private var viewModel: UserViewModel
//ViewModel 을 뷰에서 사용하기 위해 초기화
init(viewModel: UserViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
// 인터페이스 빌더를 통해 뷰 컨트롤러가 생성될 때 호출되는 초기화 메소드
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel.delegate = self
self.view.backgroundColor = .white
self.updateLayout()
self.nameLabel.text = viewModel.userName
self.ageLabel.text = String(viewModel.userAge)
// Do any additional setup after loading the view.
}
private func updateLayout() {
self.view.addSubview(nameLabel)
self.view.addSubview(ageLabel)
self.view.addSubview(button)
nameLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
}
ageLabel.snp.makeConstraints { make in
make.top.equalTo(nameLabel.snp.bottom)
make.centerX.equalToSuperview()
}
button.snp.makeConstraints { make in
make.top.equalTo(ageLabel.snp.bottom)
make.centerX.equalToSuperview()
}
}
@objc func changeAge() {
viewModel.userAge = Int.random(in: 0..<100)
}
}
extension MVVMViewController: UserViewModelDelegate {
func updateUserName(name: String) {
DispatchQueue.main.async {
self.nameLabel.text = name
}
}
func updateUserAge(age: Int) {
DispatchQueue.main.async {
self.ageLabel.text = String(age)
}
}
}
MVVM(Model-View-ViewModel) 아키텍처를 사용하여 Xcode 객체를 구현한 것입니다. MVVM은 UI 개발에서 가장 많이 사용되는 디자인 패턴 중 하나로, 모델(Model), 뷰(View), 뷰모델(ViewModel) 세 가지 구성 요소로 이루어져 있습니다.
- Model: 데이터와 비즈니스 로직을 처리하는 부분입니다. 여기서는 User 구조체가 Model에 해당합니다.
- View: 사용자에게 보여지는 UI 부분입니다. 여기서는 MVVMViewController 클래스가 View에 해당합니다.
- ViewModel: Model과 View 사이의 '다리' 역할을 합니다. View에서 필요한 데이터를 Model에서 가져와 가공한 후 View에 제공합니다. 이 코드에서는 UserViewController 클래스가 ViewModel에 해당합니다.
이 코드에서 ViewModel은 User 객체를 가지고 있고, User의 이름(name)과 나이(age)를 가져옵니다. 이 때, 이름과 나이가 변경되면, ViewModel의 delegate를 통해 View에게 알립니다.
View인 MVVMViewController는 ViewModel을 이용해 UI를 구성합니다. 뷰가 로드되면 ViewModel의 delegate를 자신으로 설정하고, ViewModel에서 제공하는 이름과 나이를 화면에 표시합니다.
또한, 나이를 변경하는 버튼이 있고, 이 버튼을 누르면 ViewModel의 나이를 랜덤한 값으로 변경합니다. 이 때 ViewModel의 나이가 변경되면, ViewModel의 delegate를 통해 View에게 알리고, View는 화면에 표시된 나이를 업데이트합니다.
이렇게 MVVM 패턴을 사용하면 Model, View, ViewModel 간의 역할이 명확하게 분리되어 코드의 가독성과 유지보수성이 향상됩니다.
Q & A
UserViewModel에서 초기화할 때 delegate: UserViewModelDelegate? = nil 을 nil값으로 준 이유가 무엇일까요?
UserViewModel 클래스에서 delegate 변수는 타입이 UserViewModelDelegate?이므로 옵셔널 타입입니다. 이는 delegate가 nil일 수도 있음을 의미합니다.
초기화 시 delegate를 nil로 설정하는 것은 일반적인 패턴입니다. delegate는 대개 뷰 컨트롤러와 같은 다른 객체에 의해 설정되며, 그 시점은 UserViewModel이 초기화된 이후일 수 있습니다.
따라서 UserViewModel이 초기화되는 시점에서는 delegate가 아직 설정되지 않았을 수 있기 때문에 nil로 초기화해두는 것입니다. 이후에 delegate가 필요한 시점에서는 delegate에 실제 객체를 할당합니다.
이 코드에서는 ProfileViewController의 viewDidLoad 메소드에서 self.viewModel.delegate = self라는 코드를 통해 delegate를 설정하고 있습니다. 이렇게 하면 UserViewModel은 delegate를 통해 ProfileViewController에게 필요한 정보를 전달할 수 있게 됩니다.
'Xcode Study' 카테고리의 다른 글
정해진 지역의 날씨를 호출하여 날씨 정보 표시하기(feat. OpenWeatherMap API) (0) | 2024.02.06 |
---|---|
How to add SwiftUI in UIkit project programmatically (0) | 2024.02.04 |
뷰 계층에서 lazy 키워드 사용하기 (0) | 2024.02.02 |
같이 일하고 싶은 개발자 (0) | 2024.01.31 |
programmatically NavigationController 만들기(feat. NavigationItem, toolbar, UINavigationControllerDelegate) (1) | 2024.01.31 |