์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- MVVM
- UIKit
- Xcode
- reactorkit
- tableView
- Lv2
- BFS
- ios
- SwiftUI
- raywenderlich
- ํ๋ก๊ทธ๋๋จธ์ค
- RxSwift
- visionOS
- Swfit
- Flutter
- ํจ์คํธ์บ ํผ์ค
- combine
- Kuring
- ๋ฐฑ์ค
- TCA
- arkit
- SnapKit
- BOJ
- CollectionView
- XCTest
- swift
- node.js
- realm
- rxcocoa
- designpattern
- Today
- Total
lgvv98
[ReactorKit] ReactorKit ๊ณต๋ถํ๊ธฐ #1 ๋ณธ๋ฌธ
[ReactorKit] ReactorKit ๊ณต๋ถํ๊ธฐ #1
๐ฅ ์บ๋ฟ๋งจ 2022. 7. 24. 02:39ReactorKit ๊ณต๋ถํ๊ธฐ #1
๐ ํด๋น ๋ฌธ์๋ ReactorKit 3.2.0์ ๊ธฐ์ค์ผ๋ก ํ๊ณ ์์ต๋๋ค.
โ ์ค๋์ ReactorKit์ ๋ํด์ ๊ณต๋ถํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
์,, ์ฌ์ ๊ณผ์ ๋ฅผ ์ํํ๋ฉด์ ์ ๋ง ์ค!๋!๋ง!์! RxSwfit๋ฅผ ๋ค์ ์ฌ์ฉํ์๋๋ฐ, ๊ธฐ๋ณธ๊ธฐ์ ๋ ์ง์คํ๋ ๊ฒ ๋๋ฌธ์ธ์ง ์ค๋๋ง์ ์ฌ์ฉํ์ด๋ ์ฌ๋ ต๊ฒ ๋๋ผ์ง์ง ์์์ต๋๋ค.
๋ค๋ง ์กฐ๊ธ ์์ฌ์ ๋ ๋ถ๋ถ์ด๋ผ๋ฉด, ํ์ตํ ๋์์ธ ํจํด์ SwiftUI ๊ธฐ๋ฐ์ ํ๋ก์ ํธ์๋ง ์ ์ฉํ๋ค ๋น์ฅ ์ ์์ฑํด์ผ ํ๋ ํ๋ก์ ํธ์์ ์ต์ ์ ๊ตฌ์กฐ๊ฐ ์ด๋ค ๊ฒ์ด์ง ๊ณ ๋ฏผํ๋ ์๊ฐ์ด ๋ง์์ ๊ฐ๋ฐ์ด ์กฐ๊ธ ์ง์ฒด๋์๋ค๋ ์ ,,,
RxSwfit๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ReactorKit๋ ์๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ๋์ ๊ณ ๊ณ !
โ ReactorKit ๊นํ๋ธ ๋ฌธ์
https://github.com/ReactorKit/ReactorKit
โ Basic Concept
๊ทธ๋ฌ๋๊น ReactorKit์ ๋ฐ์์ ์ด๊ณ ๋จ๋ฐฉํ์ ์ธ Swift ์ํคํ ์ฒ๋ฅผ ์ํ ํ๋ ์์ํฌ!
โ ReactorKit์ ๊ธฐ๋ฅ ๊ฐ์์ ์์ฑ ์ด์ ๊ฐ ๊ถ๊ธํ๋ค๋ฉด
https://www.slideshare.net/devxoul/hello-reactorkit
ReactorKit์ Flux์ Reactive Programming์ ์กฐํฉ์ด๋ค! user์ Action๊ณผ View์ ์ํ๋ observable streams์ ํตํด ๊ฐ๊ฐ์ ๋ ์ด์ด์ ์ ๋ฌ๋๋ค. ์ด๋ฌํ ์คํธ๋ฆผ์ ๋จ๋ฐฉํฅ ์คํธ๋ฆผ์ด๊ณ , ๋ทฐ๋ ์ค๋ก์ง emit action๋ง ๋ฐฉ์ถํ ์ ์๊ณ reactor๋ state๋ง ๋ฐฉ์ถํ ์ ์์ต๋๋ค.
โ ์์ ์ฝ๋๋ฅผ ๋ด ์๋ค!
1. Reactor๋ฅผ ๋จผ์ ์ ์ํฉ๋๋ค.
//
// CounterViewReactor.swift
// ReactorKitPractice
//
// Created by Hamlit Jason on 2022/07/23.
//
import Foundation
import RxSwift
import RxCocoa
import ReactorKit
class CounterViewReactor: Reactor {
/// ์ด๊ธฐ ์ํ๋ฅผ ์ ์ํฉ๋๋ค.
let initialState = State()
/// ์ฌ์ฉ์ ํ๋์ ์ ์ํฉ๋๋ค.
///
/// ์ฌ์ฉ์์๊ฒ ๋ฐ์ ์ก์
enum Action {
case increase
case decrease
}
/// ์ฒ๋ฆฌ ๋จ์๋ฅผ ์ ์ํฉ๋๋ค.
///
/// ์ก์
์ ๋ฐ์์ ๋ ๋ณํ
enum Mutation {
case increaseValue
case decreaseValue
case setLoading(Bool)
}
/// ํ์ฌ ์ํ๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
///
/// ์ด๋ ํ ๋ณํ๋ฅผ ๋ฐ์ ์ํ!
struct State {
var value = 0
var isLoading = false
}
/// Action์ด ๋ค์ด์จ ๊ฒฝ์ฐ ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ํ ๊ฒ์ธ์ง ๋ถ๊ธฐ
///
/// Mutation์์ ์ ์ํ ์์
๋จ์๋ค์ ์ฌ์ฉํ์ฌ Observable๋ก ๋ฐฉ์ถ
///
/// ์ก์
์ ๋ง๊ฒ ํ๋ํด!
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .increase:
return Observable.concat([ // concat์ ํ๋ฑํ๊ฒ ๋จผ์ ๋ค์ด์จ ์ต์ ๋ฒ๋ธ์ ์์๋๋ก ๋ฐฉ์ถ
Observable.just(.setLoading(true)),
Observable.just(.increaseValue).delay(.seconds(1), scheduler: MainScheduler.instance),
Observable.just(.setLoading(false))
])
case .decrease:
return Observable.concat([
Observable.just(.setLoading(true)),
Observable.just(.decreaseValue).delay(.seconds(1), scheduler: MainScheduler.instance),
Observable.just(.setLoading(false))
])
}
}
/// ์ด์ ์ํ์ ์ฒ๋ฆฌ ๋จ์๋ฅผ ๋ฐ์์ ๋ค์ ์ํ๋ฅผ ๋ฐํํ๋ ํจ์
///
/// mutate(action: )์ด ์คํ๋๊ณ ๋ ํ ๋ฐ๋ก ํด๋น ๋ฉ์๋๋ฅผ ์คํ
///
/// ๋ณํ์ ๋ง๊ฒ๋ ๊ฐ์ ์ค์ ํด!
func reduce(state: State, mutation: Mutation) -> State {
var newState = state
switch mutation {
case .increaseValue:
newState.value += 1
case .decreaseValue:
newState.value -= 1
case .setLoading(let isLoading):
newState.isLoading = isLoading
}
return newState
}
}
2. CounterViewController๋ฅผ ์ ์ํฉ๋๋ค.
//
// CounterViewController.swift
// ReactorKitPractice
//
// Created by Hamlit Jason on 2022/07/23.
//
import UIKit
import RxSwift
import RxCocoa
import ReactorKit
import SnapKit
class CounterViewController: UIViewController, View {
var disposeBag = DisposeBag()
let counterViewReactor = CounterViewReactor()
lazy var increaseButton = UIButton()
lazy var countLabel = UILabel()
lazy var decreaseButton = UIButton()
lazy var loadingIndicator = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
setupView()
bind(reactor: counterViewReactor)
}
func bind(reactor: CounterViewReactor) {
bindAction(reactor: reactor)
bindState(reactor: reactor)
}
private func bindAction(reactor: CounterViewReactor) {
increaseButton.rx.tap
.map { CounterViewReactor.Action.increase }
.bind(to: reactor.action)
.disposed(by: disposeBag)
decreaseButton.rx.tap
.map { CounterViewReactor.Action.decrease }
.bind(to: reactor.action)
.disposed(by: disposeBag)
}
private func bindState(reactor: CounterViewReactor) {
reactor.state
.map { "\($0.value)" }
.distinctUntilChanged()
.bind(to: countLabel.rx.text)
.disposed(by: disposeBag)
reactor.state
.map { $0.isLoading }
.distinctUntilChanged()
.bind(to: loadingIndicator.rx.isAnimating)
.disposed(by: disposeBag)
reactor.state
.map { !$0.isLoading }
.distinctUntilChanged()
.bind(to: loadingIndicator.rx.isHidden)
.disposed(by: disposeBag)
}
}
extension CounterViewController {
var margin: CGFloat {
get { return 10.0 }
}
func setupView() {
view.addSubview(increaseButton)
increaseButton.setImage(UIImage(systemName: "plus"), for: .normal)
increaseButton.snp.makeConstraints {
$0.width.height.equalTo(30)
$0.centerY.equalToSuperview()
$0.leading.equalTo(margin)
}
view.addSubview(countLabel)
countLabel.text = "0"
countLabel.snp.makeConstraints {
$0.center.equalToSuperview()
}
view.addSubview(decreaseButton)
decreaseButton.setImage(UIImage(systemName: "minus"), for: .normal)
decreaseButton.snp.makeConstraints {
$0.width.height.equalTo(30)
$0.centerY.equalToSuperview()
$0.trailing.equalTo(-margin)
}
view.addSubview(loadingIndicator)
loadingIndicator.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.centerY.equalToSuperview().offset(100)
}
}
}
typealias Reactor๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํด๋น ์ฝ๋ ํ์ผ์ ์๋ ์ฃผ์์ ReactorKit ํํธ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
https://github.com/lgvv/DesignPattern
'apple > ๐ฆ UIKit & ReactiveX' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ReactorKit] ReactorKit ๊ณต๋ถํ๊ธฐ #3 RxTodo ๋ฐ๋ผ์ก๊ธฐ (1) (0) | 2022.09.07 |
---|---|
[ReactorKit] ReactorKit ๊ณต๋ถํ๊ธฐ #2 (0) | 2022.07.24 |
[iOS] RxAction (0) | 2022.03.15 |
[RxSwift] Signal, emit (0) | 2022.02.19 |
RxSwift Community - Action ๐ฃ (0) | 2022.01.19 |