κ³°νκΉλ κ°μ μμμ λ³΄κ³ , μ 리ν λ΄μ©μ λλ€!
[1κ΅μ] RxSwift λ₯Ό μ΄μ©ν λΉλκΈ° νλ‘κ·Έλλ°
π‘ RxSwift λ λΉλκΈ° μμ μ κ²°κ³Όλ₯Ό Completion closure κ° μλ, ν¨μμ return κ°μΌλ‘ μ λ¬νκΈ° μν μ νΈλ¦¬ν° μ€ νλμ΄λ€!
π λΉλκΈ° νλ‘κ·Έλλ°, RxSwift κ° μ νμν κΉ?
λ€νΈμν¬ μμ λ± λ°μ΄ν°λ₯Ό λ°μμ€λ λ° μκ°μ΄ 걸리λ μμ μ κ²½μ°, λΉλκΈ° νλ‘κ·Έλλ°μ΄ νμνλ€.
λκΈ°(sync)λ‘ μ§νλλ€λ©΄, λ°μ΄ν°λ₯Ό λ°μμ€λ λμ λ€λ₯Έ UI μμ μ΄ μ§νλ μ μκ²λλ€.
κΈ°μ‘΄ λΉλκΈ°(async) νλ‘κ·Έλλ°μμλ λ°μ΄ν°κ° λ°μμ§λ©΄, completion closure λ‘ μ λ¬ν΄ μ΄μ©νλ€.
κ·Όλ°, closure κ° μ¬λ¬κ°κ° μ€μ²©λκ² λλ©΄ μ½λμ κ°λ μ±μ΄ λ¨μ΄μ§κ³ , μλ¬ μ²λ¦¬κ° μ΄λ ΅κ² λλ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄, closure λ‘ μ λ¬νλ κ² μλ, ν¨μμ 리ν΄κ°μΌλ‘ λ°μ΄ν°λ₯Ό μ λ¬νκΈ° μν λ°©λ²μ΄ μλ€!
"λμ€μ μκΈ°λ λ°μ΄ν°" νμ , didSet μ μ΄μ©ν΄ λ°μ΄ν°κ° μ€μ λμ λ μ²λ¦¬ν closureλ₯Ό μ§μ ν ν, λΉλκΈ° μμ μ μλ£κ°μΌλ‘ "λμ€μ μκΈ°λ λ°μ΄ν°" μΈμ€ν΄μ€λ₯Ό μ λ¬νλ€.
π RxSwift μμλ "λμ€μ μκΈ°λ λ°μ΄ν°" νμ μ μ΄λ¦μ Observable μ΄λΌκ³ λΆλ₯΄λ©°, λ°μ΄ν° κ°μ΄ λ³ν λ μνν closureλ₯Ό subscribe μ€νΌλ μ΄ν°λ₯Ό ν΅ν΄ μ§μ ν μ μλ€.
βοΈ RxSwift λ₯Ό μ¬μ©νκΈ° μν΄μλ μλ λ κ°μ§ λ°©λ²μ μλ©΄ λλ€.
1. λΉλκΈ°λ‘ μκΈ°λ λ°μ΄ν°λ₯Ό Observable λ‘ κ°μΈμ 리ν΄νλ λ°©λ²
2. Observable λ‘ μ€λ λ°μ΄ν°λ₯Ό λ°μμ μ²λ¦¬νλ λ°©λ²
1. λΉλκΈ°λ‘ μκΈ°λ λ°μ΄ν°λ₯Ό Observable λ‘ κ°μΈμ 리ν΄νλ λ°©λ²
- κΈ°λ³Έ μ¬μ©λ² :: Observable μ create ν ν, μ λ¬ν λ°μ΄ν°λ₯Ό onNext(data) λ₯Ό ν΅ν΄ μ λ¬νκ³ onCompleted() λ₯Ό ν΅ν΄ μ’ λ£νλ€. Error μ²λ¦¬κ° νμνλ€λ©΄ onError(error) λ₯Ό ν΅ν΄ μ λ¬νλ€.
- λ°μ΄ν°κ° νλλΌλ©΄, just ν μ€λ‘ μμ±νμ!
- λ°μ΄ν°κ° μ¬λ¬κ°λΌλ©΄, from μ€νΌλ μ΄ν°λ₯Ό μ΄μ©νμ!
- μ¬κΈ°μ just, from κ°μ operator λ₯Ό Sugar API λΌκ³ λΆλ₯Έλ€κ³ νλ€. (λ¬μ½€ν.. μ¬μ©λ² ?π)
// 1 κΈ°λ³Έ μ¬μ©λ²
func downloadJson(_ url: String) -> Observable<String?> {
return Observable.create { emitter in
emitter.onNext(data)
emitter.onCompleted()
return Disposables.create()
}
}
// 2 Just !
func downloadJson(_ url: String) -> Observable<String?> {
return Observable.just(data)
}
// 3 from !
func downloadJson(_ url: String) -> Observable<String?> {
return Observable.from([data1, data2])
}
2. Observable λ‘ μ€λ λ°μ΄ν°λ₯Ό λ°μμ μ²λ¦¬νλ λ°©λ²
- κΈ°λ³Έ μ¬μ©λ² :: observables.subscirbe { event in ... } λ©μλλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό λ°μμ¬ μ μλ€. closure μμ event λ₯Ό λ°μμ¬ μ μλλ°, μ΄λ next, error, completed λ‘ κ΅¬λΆλλ€. switch - case ꡬ문μ μ΄μ©ν΄ κ°κ° νμν μ½λλ₯Ό μμ±νλ€.
- μΆκ°μ μΌλ‘, subscribe νΈμΆμ κ²°κ³Όκ°μΌλ‘λ disposable μ΄ λ¦¬ν΄λλ€. μ΄λ νμμ λ°λΌ dispose() ν¨μλ₯Ό νΈμΆν΄ νμ€ν¬λ₯Ό μ·¨μν μ μλ€. μ·¨μκ° νμ μλ κ²½μ°, λ°νκ°μ _ μΌλ‘ μ λ¬λ°μΌλ©΄ κ²½κ³ λ₯Ό μμ¨ μ μλ€.
- subscribe μμ μ²λ¦¬νκ³ μΆμ event λ§ ν¨μμ 맀κ°λ³μ ννλ‘ μμ±ν μ μλ€.
// 1 κΈ°λ³Έ μ¬μ©λ²
_ = downloadJson(MEMBER_LIST_URL)
.subscribe { event in
switch event {
case .next(let json):
// main queue μμ UI μμ
λ±
case .completed:
break
case .error:
break
}
}
// 2 맀κ°λ³μ ννλ‘ μ¬μ©λ² (Sugar API?)
_ = downloadJson(MEMBER_LIST_URL)
.subscribe(onNext: { ... })
3. Operator, Sugar API ?? π€¨
- κΈ°λ³Έμ μΈ μ¬μ©λ²μ 짧κ², κ°λ¨νκ² μ¬μ©νκΈ° μν Sugar API λ₯Ό μ 곡νλλ°, μ΄λ₯Ό operator λΌκ³ νλ€.
- create, subscribe, λ°μ΄ν° μ‘°μ(map, filter) λͺ¨λ operator λΌκ³ νλ€.
- reactivex.io μμ operator μ λ§λΈ λ€μ΄μ΄κ·Έλ¨μ μ΄ν΄λ³Ό μ μλ€. (λ§λΈ λ€μ΄μ΄κ·Έλ¨μ Observable κ³Ό μ΄λ₯Ό ꡬλ νλ subscribe μμ μ΄λ»κ² λ°μ΄ν°κ° μ λ¬λλμ§λ₯Ό νμΈν΄λ³Ό μ μλ λ€μ΄μ΄κ·Έλ¨μ΄λ€.)
π operator μ΄ν΄λ³΄κΈ°
- μμμ μ΄ν΄λ³Έ just, from μ μμ±(create) μ κ΄λ ¨λ operator μ΄λ€.
- observable μ κ°μ΄ λ³ν ν λ°μ΄ν°λ₯Ό μ²λ¦¬νλ subscribe μμ main queue block μ λ§λλκ² λμ .observe(on: MainScheduler.instance) λ±μ μ¬μ©ν΄ μ°λ λλ₯Ό μ§μ νλ operator λ μλ€.
- λ°μ΄ν°κ° Subscribe λ‘ μ λ¬λκΈ° μ μ map, filter ν¨μ λ±μ μ΄μ©ν μ μλ€. κΈ°μ‘΄ Swift μμ μ΄μ©νλ ν¨μ λμκ³Ό κ°λ€.
[2κ΅μ] Observable μλͺ μ£ΌκΈ°, μ°λ λ κ΄λ¦¬
π± Observable μ μλͺ μ£ΌκΈ°
1. Create
2. Subscribed
3. Next (μν)
- - - λ - - -
4. Completed / Error
5. Disposabled
μ°Έκ³ μ¬ν
- Observable μ λ§λ€μ΄λλ€κ³ ν΄λ μ€νλμ§ μμ. subscribe ν¨μλ₯Ό νΈμΆν΄μΌλ§ μ λ¬λλ€.
- Observable μ Completed, Error λ±μΌλ‘ λλ ν μ¬μ¬μ©ν μ μλ€. dispose λ± λλ ν subscribe ν¨μλ₯Ό λ€μ νΈμΆν΄μΌλ§ μ¬μ©ν μ μλ€.
- Complted or Error λ‘ λλλ Disposabled λ‘ κ°κ³ , μ€κ°μ μ·¨μνλλΌλ Disposabled λ‘ κ°λ€.
π€ μνμ°Έμ‘°μ λ©λͺ¨λ¦¬ κ΄λ¦¬
π‘ μν μ°Έμ‘°?! λ κ°μ ν΄λμ€ μΈμ€ν΄μ€λ€μ΄ κ°νμ°Έμ‘°λ‘ μλ‘λ₯Ό λΆμ‘κ³ μμ΄, λ νΌλ°μ€ μΉ΄μ΄νΈκ° μ€μ΄λ€μ§ μκ³ , λ©λͺ¨λ¦¬μμ ν΄μ λμ§ λͺ»νλ μν©μ λ»νλ€!
- Observable μ subscribe ν λ μ λ¬λλ closure λλ¬Έμ μν μ°Έμ‘°κ° λ°μν μ μλ€.
- Closure λ μμ±λλ μμ μ ν΄λ‘μ μμ μ κ·Όνλ μΈλΆ λ³μλ€μ μΊ‘μ³λ§νμ¬ κ°κ³ μλλ€. struct κ°μ value type μ΄λ©΄ 볡μ¬λμ§λ§, class object λΌλ©΄ λ νΌλ°μ€λ₯Ό κ°κ²λμ΄ λ νΌλ°μ€ μΉ΄μ΄νΈκ° μ¦κ°νκ² λλ€. μ΄λ¬ν closure λ₯Ό ν΄μ νμ§ μλλ€λ©΄, μν μ°Έμ‘°κ° λ°μλλ κ²μ΄λ€.
- Observable μ μ€νν ν, Completed / Error / Dispose λ±μ μν΄ λλκ² λλ€λ©΄, Observable μ΄ μ¬λΌμ§κ² λμ΄ μ°Έμ‘°λ μ¬λΌμ§κ³ λ©λͺ¨λ¦¬κ° ν΄μ λλ€.
- νμ§λ§, UI μμ μ κ²½μ° λ¬΄νν μ§νλμ΄μΌνκΈ° λλ¬Έμ Completed, Error λ±μ΄ μ λ¬λμ§ μμ Observable μ΄ μ¬λΌμ§μ§ μκ³ , closure μ μν μν μ°Έμ‘°κ° λ°μν μ μλ€.
- μν μ°Έμ‘°κ° λ°μνμ§ μκΈ° μν΄ closure λ΄λΆμ [weak self] ν€μλλ₯Ό μμ±ν΄ strong μ΄ μλ weak λ νΌλ°μ€ μ°Έμ‘°λ₯Ό νκ²ν μ μλ€.
βοΈ Thread λΆκΈ°
- κΈ°μ‘΄ μ½λμμλ DispatchQueue.main.async, global.async λ±μ μ¬μ©ν΄μ λ©μΈμ°λ λμ λ³λ ¬μ°λ λλ₯Ό ꡬλΆνλ€.
- RxSwift μμ μ 곡νλ Observable μ μ€μΌμ₯΄λ¬λ₯Ό μ§μ νλ observe(on:), Subscribe μ μ€μΌμ₯΄λ¬λ₯Ό μ§μ νλ subscribe(on:) operator λ₯Ό μ΄μ©νλ©΄ μ°λ λλ₯Ό μ½κ² ꡬλΆν μ μλ€.
- μ°Έκ³ λ‘, κ°μμμλ observeOn(), subscribeOn() μ μ΄μ©νμ§λ§ μ΄λ deprecated λμ΄ μμ μμ±λ operator λ₯Ό μ΄μ©νλλ‘ νμ.
π observe(on:), subscribe(on:) κ³Ό upStream, downStream ?
- observeOn:: νμ¬ Observable μ λ€μ Observable μ΄ μ€νλ μ°λ λλ₯Ό λ³κ²½νλ€. λ°μΌλ‘ μν₯μ μ£ΌλκΉ down stream μ thread λ₯Ό λ°κΎΈλ κ²μ΄λ€.
- subscribeOn:: subscribe λ₯Ό νλ μμ μ Observable μ΄ μ€νλ μ°λ λλ₯Ό λ³κ²½νλ€. operator λ₯Ό νΈμΆνλ μμ κ³Ό μκ΄μμ΄, subscribe νλ μμ μ μ°λ λλ₯Ό μ§μ νλ μ©λμ΄λ€. μλ‘ μν₯μ μ£ΌλκΉ up stream μ thread λ₯Ό λ°κΎΈλ κ²μ΄λ€.