-
func saveData() { var encodedList = [[String: Any]]() for item in todoList { encodedList.append(item.toPropertyList()) } defaults.set(encodedList, forKey: "encodedList") }
MVVM 요약🙄
기존 MVC의 ViewController에 들어가는 데이터 관련 로직을 분리하자.
-
Model에 접근하여 처리하던 행위 ➡️ ViewModel
-
버튼, 레이블에 들어던 Title 같은 데이터도 ➡️ ViewModel
-
ViewModel를 View Controller에 표시하는 방법은 4가지
- 변수 / 바인딩 / 클로저 / Delegates클로저
-
좀 더 복잡해지는 경우, 아래 솔루션으로 MVVM을 쉽게 사용
- ReactiveCocoa
- RXSwift
To-do List로 보는 MVC vs MVVM
iOS는 UI, 비즈니스 로직의 두 가지 핵심 요소가 있음
비즈니스 로직은
- 최종 사용자 인터페이스와 데이터베이스 간의 통신을 관리
- 모델을 업데이트 하고, 데이터를 사람이 읽을 수 있게 처리하는 작업
- 데이터를 처리 (데이터 업데이트, 목록 삭제, 데이터 유형 형식 지정)
UI 로직은 최종 사용자
- 사용자 인터페이스를 다루는 부분
- 사용자가 보고 상호 작용하는 부분
- 레이블, 테이블 업데이트, 화면 구성 요소 애니메이션 등등 이쁜것들
MVC
Model : 데이터가 있는 곳, To-do에서는 할일 항목
View : 사용자가 화면에서 상호 작용하는 것, 할일 항목의 이름(레이블), 해야 할 항목의 상태 및 삭제(체크박스?)
Controller : Model과 View의 흐름 제어
MVC 사례
-
사용자가 작업 항목을 스와이프 하여 삭제 Controller ➡️ (update) Model
-
사용자가 취소 한 항목을 사용자에게 알림해주는 타이머가 있고, 시간이 만료되면 Model은 View에서 조치가 필요하다고 제어기에 알림 Controller는 View를 업데이트 하고 경고를 표시
Model ➡️ (notify: View에 업뎃필요) Controller➡️ (update) View
MVVC
View : MVC와 동일
사용자가 화면에서 상호 작용하는 것,할일 항목의 이름(레이블), 해야 할 항목의 상태 및 삭제(체크박스?`)Model : MVC와 동일
데이터가 있는 곳, To-do에서는 할일 항목View Controller : UI View를 설정, 모델과 전혀 상호 작용없음 단, View Model를 살표보고 표시 할 수 있는 형식?으로 필요한 항목을 묻고, 비즈니스 논리가 전혀 없어야함
View Model : 기본적으로 View Controller의 표현, View Controller에 레이블이 있는 경우 ViewModel에는 문자열 형식의 텍스트를 제공하는 속성이 있어야한다? 모든 호출을 트리거하고 데이터를 송수신합니다. View Controller에 독립적이어야합니다.
View Model의 인스턴스를 View Model에 삽입하면 X (잘 이해가 되지 않는다...)
MVVM의 사례
-
사용자가 작업 항목을 스와이프 하여 삭제 View Controller ➡️ (update) View
View Controller ➡️ ViewModel ➡️update Model
-
사용자가 취소 한 항목을 사용자에게 알림해주는 타이머가 있고, 시간이 만료되면 Model은 View에서 조치가 필요하다고 제어기에 알림 Controller는 View를 업데이트 하고 경고를 표시
Model ➡️ (notify: View에 업뎃필요) View Model
View Model➡️ (update: View) ViewController
ViewController ➡️ View를 업데이트
MVC의 코드 분석
일반적으로 ViewDidLoad() { } 뒤에 UI 로직을 넣음
override func viewDidLoad() { super.viewDidLoad() //MARK: UI로직 configureView() //MARK: 비즈니스로직 fetchData() } //MARK: 3. 뷰를 구성하는 메소드 func configureView() { //Only display the cells with content tableView.tableFooterView = UIView(frame: .zero) //Add color gradient to the view let gradientLayer:CAGradientLayer = CAGradientLayer() gradientLayer.frame = self.tableView.bounds gradientLayer.colors = [UIColor.red.withAlphaComponent(5).cgColor,UIColor.yellow.withAlphaComponent(0.5).cgColor] let backgroundView = UIView(frame: self.tableView.bounds) backgroundView.layer.insertSublayer(gradientLayer, at: 0) self.tableView.backgroundView = backgroundView }
일반적으로 ViewDidLoad() { } 뒤에 UI 로직이 끝난 후 비즈니스 로직을 넣음
func fetchData() { if let list = defaults.value(forKey: "encodedList") as? [[String: Any]] { for item in list { //MARK: ToDoItem은 모델 guard let todoItem = ToDoItem(item) else { return } todoList.append(todoItem) } } }
MVVM의 코드 분석
MVC와 다른 점은 ItemTableViewModel이라는 ViewModel 파일을 추가했고
viewModel를 ItemTableViewController 내 글로벌로 인스턴스화 했음
var viewModel = ItemTableViewModel() override func viewDidLoad() { super.viewDidLoad() viewModel.fetchData() configureView() }
Controller에 @IBAction
ViewController가 View을 컨트롤 하는데 있어 필요한 데이터,
아래 코드 기준으로,
alert의 제목, 메시지
todoList의 개수 등 모든 View를 표현하는데 있어 필요한 데이터를 ModelView로 정의합니다. 개인적으로 이 부분이 이해가 잘 안되는 이유가 UI 로직이라고 생각했는데, UI 로직은 UI를 만드는 행위 자체만을 정의하는거 같습니다. UI를 만들 때 필요한 데이터들은 ModelView 로 고고싱
@IBAction func didTapAdd(_ sender: Any) { let alert = UIAlertController(title: viewModel.alertTitle, message: viewModel.alertMessage, preferredStyle: .alert) alert.addTextField(configurationHandler: nil) alert.addAction(UIAlertAction(title: viewModel.actionTitle, style: .default, handler: { (_) in guard let todoTitle = alert.textFields![0].text else { return } let newIndex = self.viewModel.todoList.count self.viewModel.addToDo(todoTitle) self.tableView.insertRows(at: [IndexPath(row: newIndex, section: 0)], with: .top) self.viewModel.saveData() } )) self.present(alert, animated: true, completion: nil) }
테이블 뷰에서
모델에 접근해 지우는 경우. 모델에 업데이트 하는경우
이런 경우들을 제거 하고 ViewModel로 이동한다.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if indexPath.row < todoList.count { //모델에 접근해서 처리하는 비지니스 로직 todoList.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .top) //모델에 업데이트 하는 경우 saveData() } } func saveData() { var encodedList = [[String: Any]]() for item in todoList { encodedList.append(item.toPropertyList()) } defaults.set(encodedList, forKey: "encodedList") }
ViewModel를 View Controller에 표시하는 방법
- 변수,
var viewModel = ItemTableViewModel()
예제에서 사용된 방법
- Closur, 네트워킹 요청 및 외부 요인에 의존하는 기타 작업 시 사용 예로 API에서 데이터를 가져 오는 경우 클로저를 사용하여 ViewController를 업데이트
-
Delegates and protocols, 속성의 변경 사항을 모니터링 예로 Wi-fi가 감지되면 델리게이트를 보냄
학습할 링크 1 학습할 링크 2 학습할 링크 3MVVM 요약🙄
기존 MVC의 ViewController에 들어가는 데이터 관련 로직을 분리하자.
-
Model에 접근하여 처리하던 행위 ➡️ ViewModel
-
버튼, 레이블에 들어던 Title 같은 데이터도 ➡️ ViewModel
-
ViewModel를 View Controller에 표시하는 방법은 4가지
- 변수 / 바인딩 / 클로저 / Delegates클로저
-
좀 더 복잡해지는 경우, 아래 솔루션으로 MVVM을 쉽게 사용
- ReactiveCocoa
- RXSwift
To-do List로 보는 MVC vs MVVM비즈니스 로직은
- 최종 사용자 인터페이스와 데이터베이스 간의 통신을 관리
- 모델을 업데이트 하고, 데이터를 사람이 읽을 수 있게 처리하는 작업
- 데이터를 처리 (데이터 업데이트, 목록 삭제, 데이터 유형 형식 지정)
UI 로직은 최종 사용자
- 사용자 인터페이스를 다루는 부분
- 사용자가 보고 상호 작용하는 부분
- 레이블, 테이블 업데이트, 화면 구성 요소 애니메이션 등등 이쁜것들
MVC
Model : 데이터가 있는 곳, To-do에서는 할일 항목
View : 사용자가 화면에서 상호 작용하는 것, 할일 항목의 이름(레이블), 해야 할 항목의 상태 및 삭제(체크박스?)
Controller : Model과 View의 흐름 제어
MVC 사례
-
사용자가 작업 항목을 스와이프 하여 삭제 Controller ➡️ (update) Model
-
사용자가 취소 한 항목을 사용자에게 알림해주는 타이머가 있고, 시간이 만료되면 Model은 View에서 조치가 필요하다고 제어기에 알림 Controller는 View를 업데이트 하고 경고를 표시
Model :arrow_right: (notify: View에 업뎃필요) Controller:arrow_right: (update) View
MVVC
View : MVC와 동일
사용자가 화면에서 상호 작용하는 것,할일 항목의 이름(레이블), 해야 할 항목의 상태 및 삭제(체크박스?`)Model : MVC와 동일
데이터가 있는 곳, To-do에서는 할일 항목View Controller : UI View를 설정, 모델과 전혀 상호 작용없음 단, View Model를 살표보고 표시 할 수 있는 형식?으로 필요한 항목을 묻고, 비즈니스 논리가 전혀 없어야함
View Model : 기본적으로 View Controller의 표현, View Controller에 레이블이 있는 경우 ViewModel에는 문자열 형식의 텍스트를 제공하는 속성이 있어야한다? 모든 호출을 트리거하고 데이터를 송수신합니다. View Controller에 독립적이어야합니다.
View Model의 인스턴스를 View Model에 삽입하면 X (잘 이해가 되지 않는다...)
MVVM의 사례
-
사용자가 작업 항목을 스와이프 하여 삭제 View Controller ➡️ (update) View
View Controller ➡️ ViewModel ➡️update Model
-
사용자가 취소 한 항목을 사용자에게 알림해주는 타이머가 있고, 시간이 만료되면 Model은 View에서 조치가 필요하다고 제어기에 알림 Controller는 View를 업데이트 하고 경고를 표시
Model :arrow_right: (notify: View에 업뎃필요) View Model View Model:arrow_right: (update: View) ViewController ViewController :arrow_right: View를 업데이트
MVC의 코드 분석
일반적으로 ViewDidLoad() { } 뒤에 UI 로직을 넣음
override func viewDidLoad() { super.viewDidLoad() //MARK: UI로직 configureView() //MARK: 비즈니스로직 fetchData() } //MARK: 3. 뷰를 구성하는 메소드 func configureView() { //Only display the cells with content tableView.tableFooterView = UIView(frame: .zero) //Add color gradient to the view let gradientLayer:CAGradientLayer = CAGradientLayer() gradientLayer.frame = self.tableView.bounds gradientLayer.colors = [UIColor.red.withAlphaComponent(5).cgColor,UIColor.yellow.withAlphaComponent(0.5).cgColor] let backgroundView = UIView(frame: self.tableView.bounds) backgroundView.layer.insertSublayer(gradientLayer, at: 0) self.tableView.backgroundView = backgroundView }
일반적으로 ViewDidLoad() { } 뒤에 UI 로직이 끝난 후 비즈니스 로직을 넣음
func fetchData() { if let list = defaults.value(forKey: "encodedList") as? [[String: Any]] { for item in list { //MARK: ToDoItem은 모델 guard let todoItem = ToDoItem(item) else { return } todoList.append(todoItem) } } }
MVVM의 코드 분석
MVC와 다른 점은 ItemTableViewModel이라는 ViewModel 파일을 추가했고
viewModel를 ItemTableViewController 내 글로벌로 인스턴스화 했음
var viewModel = ItemTableViewModel() override func viewDidLoad() { super.viewDidLoad() viewModel.fetchData() configureView() }
Controller에 @IBAction
ViewController가 View을 컨트롤 하는데 있어 필요한 데이터,
아래 코드 기준으로,
alert의 제목, 메시지 todoList의 개수 등 모든 View를 표현하는데 있어 필요한 데이터를 ModelView로 정의합니다. 개인적으로 이 부분이 이해가 잘 안되는 이유가 UI 로직이라고 생각했는데, UI 로직은 UI를 만드는 행위 자체만을 정의하는거 같습니다. UI를 만들 때 필요한 데이터들은 ModelView 로 고고싱
@IBAction func didTapAdd(_ sender: Any) { let alert = UIAlertController(title: viewModel.alertTitle, message: viewModel.alertMessage, preferredStyle: .alert) alert.addTextField(configurationHandler: nil) alert.addAction(UIAlertAction(title: viewModel.actionTitle, style: .default, handler: { (_) in guard let todoTitle = alert.textFields![0].text else { return } let newIndex = self.viewModel.todoList.count self.viewModel.addToDo(todoTitle) self.tableView.insertRows(at: [IndexPath(row: newIndex, section: 0)], with: .top) self.viewModel.saveData() } )) self.present(alert, animated: true, completion: nil) }
테이블 뷰에서
모델에 접근해 지우는 경우. 모델에 업데이트 하는경우
이런 경우들을 제거 하고 ViewModel로 이동한다.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if indexPath.row < todoList.count { //모델에 접근해서 처리하는 비지니스 로직 todoList.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .top) //모델에 업데이트 하는 경우 saveData() } } func saveData() { var encodedList = [[String: Any]]() for item in todoList { encodedList.append(item.toPropertyList()) } defaults.set(encodedList, forKey: "encodedList") }
ViewModel를 View Controller에 표시하는 방법
-
변수,
var viewModel = ItemTableViewModel()
예제에서 사용된 방법 -
바인딩, ViewModel Class를 View Controller에 바인딩하는 클래스?! 값과 이벤트를 바로 뷰에 적용하는 것!?
-
Closur, 네트워킹 요청 및 외부 요인에 의존하는 기타 작업 시 사용 예로 API에서 데이터를 가져 오는 경우 클로저를 사용하여 ViewController를 업데이트
-
Delegates and protocols, 속성의 변경 사항을 모니터링 예로 Wi-fi가 감지되면 델리게이트를 보냄
-
- iOS는 UI, 비즈니스 로직의 두 가지 핵심 요소가 있음
[참고 링크 - twilio.com
댓글
-