raywenderlich RxSwift Ch5~6
Swift ์ ๊ฒฝ์ฐ๋ ์ต์ ๋ฒ์ ผ์์๋ ๋ฌธ๋ฒ์ ๋ง๊ฒ, elementAt -> element(at: ), takeWhile -> take(while: ) ์ด๋ฐ์์ผ๋ก ๋ฐ๋์ด ์์๋ค.
Observable.of(2, 2, 3, 4, 4)
.skip(while: {
// ์ด ๊ฒฝ์ฐ์๋ ์กฐ๊ฑด์ ๋ง์ง ์๋ 3๋ถํฐ ์ถ๋ ฅ๋๋ค.
$0 % 2 == 0
})
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 3 4 4
<-> Skipping
+) Observable ์๋ .enumerated() ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ค๋ณตํด์ ์ด์ด์ง๋ ๊ฐ์ ์์ ์ค๋ค.
distinctUntilChanged {
$0.lastName == $1.lastName
}
#6์์ ์งํํ๋ ํ๋ก์ ํธ๋ฅผ Filtering Object ๋ฅผ ์ด์ฉํด์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ ๋ฆฌํฉํ ๋ง ํด๋ณด์๋ค. ์ญ์ ๋ฐ๋ผ๊ฐ๋ฉด์ ๊ธฐ์ต์ ๋จ๋ ๊ฒ๋ค ์์ฃผ๋ก ํฌ์คํ ํด๋ณด๋ ค๊ณ ํ๋ค.
Observable ์ ๊ตฌ๋ ๋ ๋๋ง๋ค create ๋ฅผ ํธ์ถํ๊ธฐ ๋๋ฌธ์, ๊ฐ์ Observable ์ ๊ตฌ๋ ํด๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์๋ค. ๊ฒ๋ค๊ฐ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๊ฑด๋ฐ Observable ์ ๊ตฌ๋ ์ ๋ณ๋ก ๋ค๋ฅด๊ฒ ์ ์งํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ค.
๊ทธ๋์ ํ๋์ ๊ตฌ๋ ์ ๊ณต์ ํ๊ธฐ ์ํด์ share() ๋ฅผ ์ด์ฉํ๋ค.
let newImage = photosViewController.selectedPhotos.share() // newImage ๋ฅผ ๊ตฌ๋ ํ์ฌ ๊ฐ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ฉด ๋๋ค.
share()
: ๊ตฌ๋
์ด ์ํฅ์ ๋ฐ๊ธฐ ์ ๊น์ง๋ ์ด๋ค ๊ฐ๋ ๋ฐฉ์ถํ์ง ์๋๋ค.share(replay: , scope: )
๋ ๋ง์ง๋ง ๋ช ๊ฐ์ ๋ฐฉ์ถ๊ฐ์ ๋ํ ๋ฒํผ๋ฅผ ์ ๊ณตํ๋ค. (์๋ก์ด ๊ตฌ๋
์์๊ฒ ๋ง์ง๋ง ๋ช ๊ฐ๋ฅผ ๋ฐ์ถํ๋ค.)sharing
์ ๊ฒฝ์ฐ completed ๋์ง ์๋ Observable ์ ์ฌ์ฉํ๋ค.Observable ์ ํ์ฌ ๊ฐ์ด๋ ํ์คํ ๋ฆฌ๋ฅผ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ ํน์ ์์๋ฅผ ํ์ธํ๊ธฐ ์ํด์๋ ๊ฐ ์์ ์์ฒด๊ฐ ์ค์ค๋ก๋ฅผ ์ถ์ ํ๊ฒ ํด์ผํ๋ค.
// imageCache ๋ฐฐ์ด๋ก, ์ด๋ฏธ ์๋ ์ด๋ฏธ์ง์ธ์ง ํ์ธํ๋ ๊ณผ์ ์ ๊ฑฐ์ณค๋ค. .filter { [weak self] newImage in // ๋ณดํต assetId ๊ฐ์ ๊ฒ์ ์ด์ฉํ์ง๋ง, ์์ ๋ผ์ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋น๊ต. let len = newImage.pngData()?.count ?? 0 guard self?.imageCache.contains(len) == false else { return false } self?.imageCache.append(len) return true }
10์ค์ง๋ฆฌ ์ฝ๋๋ฅผ 3์ค๋ก ์ค์ด๋ ๊ฒ๋ง์ด ์ข์ ๋ฆฌํฉํ ๋ง ๋ฐฉ์์ด ์๋๋ค!! ์์ ์์๋ PHPhotoLibrary ์ ์ฌ์ง ์ ๊ทผ ๊ถํ ๊ด๋ จ ์ฝ๋๋ฅผ ์ธ ๋, ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์งฐ๋ค.
// ์น์ธ์ด ๋์ด ์์ผ๋ฉด true
// ์๋์ด ์์ผ๋ฉด false ๋ณด๋ด๊ณ ๋ค์ ๊ถํ ์์ฒญํด์ ๊ฒฐ๊ณผ๊ฐ
extension PHPhotoLibrary {
static var authorized: Observable<Bool> {
return Observable.create() { observer in
if authorizationStatus() == .authorized {
observer.onNext(true)
observer.onCompleted()
} else {
observer.onNext(false)
requestAuthorization { newStatus in
observer.onNext(newStatus == .authorized)
observer.onCompleted()
}
}
return Disposables.create()
}
}
}
- ๊ผญ ์ธ ํ์๊ฐ ์์ด๋ ์ฝ๋๋ฅผ ํ๋์ค ์ถ๊ฐํด์ ์๋ฏธ๊ฐ ๋ช ํํด์ง๊ณ ์ฝ๊ธฐ ํธํด์ง๋ค๋ฉด ๊ทธ๋ ๊ฒ ํ์!
// ์ด์ฐจํผ ์ฑ์ ๋งจ ์ฒ์ ์ผ๊ณ ์ฒซ๋ฒ์งธ ๊ฐ์ false ์. // ๊ถํ ์น์ธ์ ํด์ค์ ๊ฐ์ด true ์ผ ๋ let authorized = PHPhotoLibrary.authorized.share() authorized .skipWhile { $0 == false } .take(1) // ์ธ ํ์๊ฐ ์์ง๋ง ์๋ฏธ๊ฐ ๋ช ํํด์ง๋ค. .subscribe(onNext: { [weak self] _ in self?.photos = PhotosViewController.loadPhotos() DispatchQueue.main.async { self?.collectionView?.reloadData() } }) .disposed(by: bag)
filter{$0 == false}
== filter{!$0}
== filter{!}
๋ฌผ๋ก ์ค์ฌ์ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ ์ค์ฌ ์จ๋ ๊ด์ฐฎ์.
- Observable ์์ ๋์ด์ค๋ ๋ฐ์ดํฐ์ sequence ๊ฐ
์ ๋๋ถ๋ณ
ํ ๋ก์ง์ด ์๋๋ผ๋ฉด ๋ก์ง์ ์๋ตํ์ง ๋ง์.// ๊ถํ ์น์ธ์ ๊ฑฐ์ ํด์ ๊ฐ์ด false ์ผ ๋ // ์ด์ฐจํผ ์ฑ ์ฒ์ ์ผ false, ๊ถํ ์น์ธ ๊ฑฐ์ false ๋ก 2๊ฐ์ ๊ฐ์ด ์ค์ง๋ง skip, takeLast๋ฅผ ๋ ๋ค ํ ๊ฒ ์ฒ๋ผ ๋ก์ง์ ์๋ตํ์ง ๋ง์. // _ = authorized .skip(1) .takeLast(1) .filter { $0 == false } .subscribe(onNext: { [weak self] _ in guard let errorMessage = self?.errorMessage else { return } DispatchQueue.main.async(execute: errorMessage) })
๋๋ฌด ๋ง์ ์ฌ์ฉ์ ์ ๋ ฅ๊ฐ์ ๊ฑธ๋ฌ์ฃผ๋ ์ฝ๋๋ก
์ฌ๋ฌ๋ฒ ๋ค์ด์ค๋ ๋์ผ ์ด๋ฒคํธ๋ฅผ ํ๋ฒ๋ง ์ ๋ฌํ๋ค.// 0.5 ์ด๊ฐ ๋ค์ด์ค๋ ์ ๋ ฅ์ ๋ชจ์์ ๋ฐ์ํ๋ค. // ์ฆ๊ฐ์ ์ผ๋ก ๋ฐ์ํ์ง ์๊ฒ! .throttle(0.5, scheduler: MainScheduler.instance)
์ฐ๋ฆฌ๊ฐ ๋ง๋ ์์ ์์๋ ์ฌ์ฉ์๊ฐ ์ฌ์ง์ ์ ํํ ๋๋ง๋ค ์๋ก์ด ์ฝ๋ผ์ฃผ๋ฅผ ๋ง๋๋๊ฒ ์์ ๋ญ๋น์ด๋ฏ๋ก, 0.5์ด ๋ด์ ์ ํ๋๋ ์ฌ๋ฌ๊ฐ์ ์ฌ์ง์ ๋ํด์๋ ์ผ์ผ์ด ์ฝ๋ผ์ฃผ๋ฅผ ๋ง๋ค์ง ์๊ฒ throttle ์ ๊ฑธ์๋ค.
์ด ์ธ์๋ textField ์
๋ ฅํ ๋๋
๋ชจ๋ฌ์ด ๋จ๊ธฐ ์ ์ ๋ฒํผ์ ์ฐํํ์ ๋ ๋ชจ๋ฌ์ด ์ฌ๋ฌ๊ฐ ๋จ์ง ์๋๋ก ๋ฐฉ์ง ํ๋ค๋๊ฐ
๋๋๊ทธ ํ ๋ ๋๋๊ทธ ๋๋๋ ์์น๋ง ์๊ณ ์ถ์ ๋ ์ฌ์ฉํ ์ ์๋ค.
debounce ๋ ์์ ์๋ ์์์ง๋ง throttle ๊ณผ ํญ์ ๋ฌถ์ฌ์ ๋ค๋๋ ๊ฐ๋ ์ธ ๊ฒ ๊ฐ์์ ํจ๊ป ์ฐพ์๋ดค๋ค.
debounce ๋ ์ผ์ ์๊ฐ๋์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ๋ชจ์์!! ํ๋ฒ์ ์ ๋ฌํ๋ค.
debounce(for: .seconds(2), lastest: true, scheduler: MainScheduler.instance)
์ง์ ๋ ์๊ฐ 2์ด ์์์ ๋ง์ง๋ง์ ๋ค์ด์จ ๊ฒ์ emitํ๋ ์ต์ ์ธ lastest ๋ฅผ ์ค์ ํ ์ ์๋ค. ๊ธฐ๋ณธ๊ฐ์ด true! (throttle ๋ ์ค์ ํ ์ ์๋ค.)
latest: false
์ด๋ฉด ์ฒซ๋ฒ์งธ ๊ฐ๋ง์ emit ํ๊ณ 2์ด ๋์ ๋ค์ด์ค๋ ๊ฐ์ ๋ค ๋ฌด์ํ ๋ค, 2์ด๊ฐ ์ง๋๊ณ ๋์ ์ธ์ ๊ฐ ๋ ๋ค์ด์ค๋ ์ฒซ๋ฒ์งธ ๊ฐ๋ง emit ํ๊ฒ ๋๋ค.
filtering operator ๊ฐ ๊ทธ๋ ๊ฒ ์ด๋ ต์ง ์๋ค๊ณ ์๊ฐํ๋๋ฐ, takeWhile, skipWhile ์ด ์๊ฐ๋ณด๋ค ํท๊ฐ๋ ธ๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ ์๋๊ฒ ๋ค๊ฐ ์๋๋ผ ๋ ์์ฃผ ๋ง์.. operator ๋ค์ด ์๋ค๊ณ ์๊ฐํ๋๊น ์ ์์ ๊ธฐ์ ๋ง๋ ๊ฒ์ ์ฐพ์ ์ฐ๋ ๊ฒ๋ ์ด๋ ค์ธ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
PHPhotoLibrary.autorized
๋ฅผ Observable ์ ์ด์ฉํด์ ๋ค๋ฃจ๋๊ฒ ์ ๊ธฐํ๋ค. ์ฌํ ํจ์ return ๊ฐ์ผ๋ก๋ง ์คฌ์๋๋ฐ, computed property ๋ฅผ ์ฌ์ฉํด์๋ Observable ์ ์ฌ์ฉํ ์ ์๋ค๋๊ฒ.. ๋ฐฐ์ธ ๋ถ๋ถ์ด ์์ฒญ ๋ง์ ๊ฒ ๊ฐ๋ค.
์ถ์ฒ - https://github.com/fimuxd/RxSwift/tree/master/Lectures
์ด๋ฏธ์ง ์ถ์ฒ - https://reactivex.io/