Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- Observable
- SWIFT
- Protocol
- RxCocoa
- Clean Code
- Xcode
- UICollectionView
- HIG
- collectionview
- 리펙터링
- 리팩토링
- rxswift
- MVVM
- combine
- UITextView
- uitableview
- tableView
- swiftUI
- 스위프트
- ribs
- map
- swift documentation
- 리펙토링
- 클린 코드
- ios
- Human interface guide
- Refactoring
- 애니메이션
- clean architecture
- uiscrollview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 4. ReactorKit - `TaskEdit 구현`, 화면전환, 데이터 전달 본문
Architecture (swift)/ReactorKit
[iOS - swift] 4. ReactorKit - `TaskEdit 구현`, 화면전환, 데이터 전달
jake-kim 2021. 12. 3. 02:232. ReactorKit - 테스트 방법 (Storyboard 사용, IBOutlet 테스트 방법)
3. ReactorKit - `TaskList 구현`, 템플릿 (template), 비동기 처리 transform(mutation:)
4. ReactorKit - `TaskEdit 구현`, 화면전환, 데이터 전달
* ReactorKit과 RxDataSources 사용 방법은 이곳 참고
ReactorKit 구현 방향
- View, Reactor 생성
- View의 storyboard에 UI 생성, IBOutlet 입력
- Reactor의 Action 정의, Action에 해당하는 Mutation, State 정의
- Reactor에서 필요한 service 정의
- Reactor의 mutate, reduce 정의
TaskEdit 구현
- 화면전환 TaskList -> TaskEdit
- TaskEditReactor는 생성자로 taskService를 가지고 있고, 이 값은 TaskList에서 가지고 있는 인스턴스를 주입
// TaskEditReactor.swift init(initialState: State, taskService: TaskService) { self.initialState = initialState self.taskService = taskService }
- TaskList의 Action에 TaskEdit으로 보내는 Action 추가
enum Action { case didInitBinding case didSelect(IndexPath) case didTapAddButton // <- }
- TaskList의 Mutation와, State에 present관련 값 추가
- Mutation의 setIsPresentEditTask(Bool):
- State의 isPresentEditTask:
- TaskEditReactor는 생성자로 taskService를 가지고 있고, 이 값은 TaskList에서 가지고 있는 인스턴스를 주입
enum Mutation {
case setSections([TaskListSection])
case updateSectionItem(IndexPath, TaskListSection.Item)
case insertSectionItem(IndexPath, TaskListSection.Item)
case setIsPresentEditTask(Bool) // <-
}
struct State {
var sections: [TaskListSection]
/// Bool 값은 영구적이므로, sections값이 변경되면 isPresentEditTask도 방출되면서 isPresentEditTask 옵저버가 계속 실행
/// Mutation에서 concat으로 true > false로 바꾸어주는 로직 필요
var isPresentEditTask: Bool = false
}
- didTapAddButton이 오면, concat으로 presentEditTask를 true로 바꾸었다가, false로 변경
- true로 계속 되어있으면 sections값들이 바뀌어도 ViewController에 같이 emit되므로 false로 변경 필요
func mutate(action: Action) -> Observable<Mutation> {
var newMutation: Observable<Mutation>
switch action {
case .didInitBinding:
newMutation = getRefreshMutation()
case .didSelect(let indexPath):
newMutation = setCheckMarkMutation(indexPath)
case .didTapAddButton:
newMutation = getPresentEditTaskMutation() // <-
}
return newMutation
}
...
private func getPresentEditTaskMutation() -> Observable<Mutation> {
return Observable.concat([
Observable.just(.setIsPresentEditTask(true)),
Observable.just(.setIsPresentEditTask(false)) // <-
])
}
...
func reduce(state: State, mutation: Mutation) -> State {
var newState = state
switch mutation {
case .setSections(let sections):
newState.sections = sections
case .updateSectionItem(let indexPath, let item):
newState.sections[indexPath.section].items[indexPath.item] = item
case .insertSectionItem(_, let item):
newState.sections[0].items.insert(item, at: 0)
case .setIsPresentEditTask(let isPresent): // <-
newState.isPresentEditTask = isPresent
}
return newState
}
- 화면전환, 데이터 전달
- TaskListViewController에서는 isPresentEditTask를 구독하고 있다가, 이벤트 발생시 화면전환
- 화면전환시 필요한 TaskEditReactor 인스턴스는 TaskListReactor에서 정의
// TaskListReactor.swift
func getTaskEditReactorForCreatingTask() -> TaskEditReactor {
return TaskEditReactor(initialState: TaskEditReactor.State(title: ""), taskService: taskService)
}
// TaskListViewController.swift
private func bindState(_ reactor: TaskListReactor) {
reactor.state
.map { $0.isPresentEditTask }
.distinctUntilChanged()
.filter { $0 }
.map { _ in reactor.getTaskEditReactorForCreatingTask() } // <-
.bind(onNext: presentTaskEditViewController)
.disposed(by: disposeBag)
}
private func presentTaskEditViewController(reactor: TaskEditReactor) {
let storyboard = UIStoryboard(name: "TaskEdit", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: TaskEditViewController.className) as! TaskEditViewController
viewController.reactor = reactor
present(viewController, animated: true)
}
cf) ReactorKit을 이용한 샘플 앱
- ReactorKit 샘플 앱 - RxDataSources을 이용한 Section, Item 모델 구현 패턴 (with 동적 사이즈 셀)
* 전체 코드: https://github.com/JK0369/ExTaskUsingReactorKit/tree/Router
'Architecture (swift) > ReactorKit' 카테고리의 다른 글
Comments