๐ RxSwift
โ Rx๊ฐ ์์ด UI ์ค๊ณ
ํ ์คํธ ํ๋ ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ ์ก์
ํ ์คํธ ์ฒด์ธ์ง ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ณ
ํจ์ค์๋๋ ์์ด๋ ๋ถ๊ธฐ๋ฅผ ์ก๊ณ
valid ์ฒดํฌํ๊ณ true false๋ฅผ ํตํด hidden ์ on off ํจ
๋๋ค valid ๋ง์ผ๋ฉด ๋ฒํผ์ hidden off
โญ๏ธ Rx๋ฅผ ์ฌ์ฉํด UI ์ค๊ณ
๋ฐ์ดํฐ๊ฐ ํ์ํ๋ฐ ๋์ค์ ๋ฐ์ดํฐ๋ฅผ ์ค ๋ ๋น๋๊ธฐ ์ฌ์ฉ
์์ด๋๋ ๋น๋ฐ๋ฒํธ๋ฅผ ๋๋ ์ ๋ ๊ฐ์ ๋์ค์ ์ฃผ๋๊น ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๊ฐ๋ฅ
์คํธ๋ฆผ์ ํด๋ฆญ์ด๋ฒคํธ, ํ ์คํธ ์ฒด์ธ์ง ์ด๋ฒคํธ๋ฅผ ๋ฃ๊ณ ์๋ธ์คํฌ๋ผ์ ์ ์ ๋ฌ๋จ
UI ์ด๋ฒคํธ๊ฐ ์ฒ๋ฆฌ๋๋ ๊ฒ๋ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ
โญ๏ธ ์์ฉ
์ฒซ ์ฝ๋ฉ
private func bindUI() {
idField.rx.text
// .filter{ $0 != nil }
// .map{ $0! }
.orEmpty
.map(checkEmailValid)
.subscribe(onNext: { b in
self.idValidView.isHidden = b
})
.disposed(by: disposeBag)
pwField.rx.text
// .filter{ $0 != nil }
// .map{ $0! }
.orEmpty
.map(checkPasswordValid)
.subscribe(onNext: { b in
self.pwValidView.isHidden = b
})
.disposed(by: disposeBag)
Observable.combineLatest( // ๋ค์ํ ๋ฉ์๋๊ฐ ์๋ค. merge, zip ๋ฑ๋ฑ , ์ด๊ฒ๋ค์ค ์ฌ๊ธฐ์ ์ ์ผ ์ด์ธ๋ฆฌ๋ ๊ฒ์ combineLatest
idField.rx.text.orEmpty.map(checkEmailValid),
pwField.rx.text.orEmpty.map(checkPasswordVaild),
resultSelector: { s1, s2 in s1 && s2 } // ๋จผ์ ๋ด๋ ค์จ ์ ์ฐฉ์์ผ๋ก s1, s2 ๊ฒฐ์
)
.subscribe(onNext : { b in
self.loginButton.isEnabled = b
})
.disposed(by : disposeBag)
}
๋ฆฌํฉํ ๋ง (์ค๋ณต ์ ๊ฑฐ)
private func bindUI() {
let idInputOb = idField.rx.text.orEmpty.asObservable() // ๋ช
ํํ๊ฒ ํ๊ธฐ ์ํ asObservable()
let pwInputOb = pwField.rx.text.orEmpty.asObservable()
let emailValidOb = idInputOb.map(checkEmailValid)
let pwValidOb = pwInputOb.map(checkPasswordValid)
idValidOb
.subscribe(onNext : {b in self.idValidView.isHidden = b})
.disposed(by: disposeBag)
pwValidOb
.subscribe(onNext : {b in self.idValidView.isHidden = b})
.disposed(by: disposeBag)
Observable.combineLatest(idValidOb, pwValidOb, resultSelector : {$0 && $1})
.subscribe(onNext : {b in self.loginButton.isEnable = b})
.disposed(by: disposeBag)
}
โญ๏ธ Subject
- AsyncSubject
- ๋์ด๋๋ฉด ๋ง์ง๋ง์ ์๋ ๋ฐ์ดํฐ๋ง ๋๊ฒจ์ค๋ค.
- BehaviorSubject
- ๋ํดํธ ๊ฐ์ด ์์, ์ด ๊ฐ์ ๋ฃ๊ณ ์์ํจ
- Subscribeํ๋ ๋์ค ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ๋ค๋ฅธ subscribe์๋ ์๋ฌ๋ฅผ ๋ฐ์์ํด
- PublishSubject
- ๋ํดํธ ๊ฐ์ด ์์
- ReplaySubject
- ์ค๊ฐ์ subscribe์ ํ๋ฉด ์ ์ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค ๋๊ฒจ์ฃผ๊ณ ๊ทธ๋ค์ ๋๊ฒจ์ค๋ค.
subject ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค ์๋ ์๊ณ Subscribe ํด์ค ์๋ ์๋ ์น๊ตฌ๋ค.
// ํจ์ ๋ฐ์ Subject ๋ฅผ ์์ฑํจ
let idValid : BehaviorSubject<Bool> = BehaviorSubject(value: false)
let idInputText : BehaviorSubject<String> = BehaviorSubject(value: "")
let pwValid : BehaviorSubject<Bool> = BehaviorSubject(value: false)
let pwInputText : BehaviorSubject<String> = BehaviorSubject(value: "")
private func bindInput() {
/* ---------id---------- */
// let idInputOb = idField.rx.text.orEmpty.asObservable() // ๋ช
ํํ๊ฒ ํ๊ธฐ ์ํ asObservable()
// let idValidOb = idInputOb.map(checkEmailValid)
// Subject์ ๊ฐ ๋ฃ์ด์ฃผ๋ ๋ฒ 1
// idValidOb.subscribe(onNext : { b in
// self.idValid.onNext(b)
// })
// Subject์ ๊ฐ ๋ฃ์ด์ฃผ๋ ๋ฒ 2
// idValidOb.bind(to : idValid)
// Subject ์ ์ฉ์ - idText ๋ด๋ณด๋ด๊ธฐ
idField.rx.text.orEmpty
.bind(to : idInputText)
.disposed(by: disposeBag)
// Subject ์ ์ฉ์ - idValid ๋ด๋ณด๋ด๊ธฐ
idField.rx.text.orEmpty // <- ์ฌ๊ธฐ๋ค๊ฐ ์์์ idText๋ฅผ ๋ด๋ณด๋ธ subject ๋ฅผ ๋ฃ์ด์ค ์ ์๋ค. (idInputText)
.map(checkEmailValid) // ์ด๋ฉ์ผ ์ฒดํฌํ ๊ฒฐ๊ณผ๋ฅผ
.bind(to: idValid) // ๋ฐ์ ์ธ๋ถ์ idValid๋ผ๊ณ ํ๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ด์๊ฒ์.
.disposed(by: disposeBag)
/* ---------pw---------- */
// let pwInputOb = pwField.rx.text.orEmpty.asObservable()
// let pwValidOb = pwInputOb.map(checkPasswordValid)
// Subject์ ๊ฐ ๋ฃ์ด์ฃผ๋ ๋ฒ 1
// pwValidOb.subscribe(onNext : { b in
// self.pwValid.onNext(b)
// })
// Subject์ ๊ฐ ๋ฃ์ด์ฃผ๋ ๋ฒ 2
// pwValidOb.bind(to : pwValid)
// Subject ์ ์ฉ์ - pwText ๋ด๋ณด๋ด๊ธฐ
pwField.rx.text.orEmpty
.bind(to : idInputText)
.disposed(by: disposeBag)
// Subject ์ ์ฉ์ - idValid ๋ด๋ณด๋ด๊ธฐ
pwField.rx.text.orEmpty // <- ์ฌ๊ธฐ๋ค๊ฐ ์์์ pwText๋ฅผ ๋ด๋ณด๋ธ subject ๋ฅผ ๋ฃ์ด์ค ์ ์๋ค. (pwInputText)
.map(checkPasswordValid) // ์ด๋ฉ์ผ ์ฒดํฌํ ๊ฒฐ๊ณผ๋ฅผ
.bind(to: pwValid) // ๋ฐ์ ์ธ๋ถ์ idValid๋ผ๊ณ ํ๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ด์๊ฒ์.
.disposed(by: disposeBag)
}
private func bindOutput() {
idValid
.subscribe(onNext : {b in self.idValidView.isHidden = b})
.disposed(by: disposeBag)
pwValid
.subscribe(onNext : {b in self.idValidView.isHidden = b})
.disposed(by: disposeBag)
Observable.combineLatest(idValid, pwValid, resultSelector : {$0 && $1})
.subscribe(onNext : {b in self.loginButton.isEnable = b})
.disposed(by: disposeBag)
}
input ๊ณผ output๊ฐ ๋ถ๋ฆฌ๋ ์ ์์๋ ์ด์ ๋ subject๋ฅผ ํตํด์ ๋ฐ๊นฅ์ผ๋ก ๋์ง์ด ๋ผ ์ ์์๊ธฐ ๋๋ฌธ์ด๋ค.
bind ๋ฅผ ๋ณด๋ SwiftUI ์ Binding์ด๋ ์กฐ๊ธ ๋น์ทํ๊ฑฐ ๊ฐ๊ธฐ๋โฆ
Ref
https://www.youtube.com/watch?v=w5Qmie-GbiA&list=PL03rJBlpwTaAh5zfc8KWALc3ADgugJwjq&index=1
'iOS > RxSwift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] RxSwift - ๊ธฐ๋ณธ ๋ฌธ๋ฒ ์ ๋ฆฌ (0) | 2022.07.23 |
---|