Swift Extension Cheat Sheet
๐ RxSwift Extension Cheat Sheet โ ์ค๋ฌด์ ๋ฐ๋ก ์ฐ๋ ์ ํธ ๋ชจ์
โRx ์คํผ๋ ์ดํฐ๊ฐ ๋ถ์กฑํ ๋, ์ฐ๋ฆฌ๋ง์ ํ ์ค์ ๋!โ
์๋ ํ์ฅ๋ค์ ๋ชจ๋ Observable / Single / Driver / ControlEvent ๋ฑ Rx ํ์ ์ ๋ค๋ฃน๋๋ค. ์์ Swift ์ ํธ(๋ฌธ์์ด, ๋ฐฐ์ด ๋ฑ)์ ์ ์ธํ์ผ๋, Rx ํ๋ฆ์์ ๋ฐ๋ก ๋ณต์ฌยท๋ถ์ฌ๋ฃ๊ณ ์ฌ์ฉํด ๋ณด์ธ์.
1๏ธโฃ Observable โถ Driver/Signal ๋ณํ
import RxSwift
import RxCocoa
extension ObservableType {
/// ์๋ฌ๋ฅผ ๋ฌด์ํ๊ณ Completed ์ฒ๋ฆฌํ์ฌ Driver๋ก ๋ณํ
func asDriverOnErrorJustComplete() -> Driver<Element> {
asDriver { _ in .empty() }
}
/// ์๋ฌ ๋ฐ์ ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋์ฒดํ ๋ค Driver ๋ฐํ
func asDriver(onErrorJustReturn value: Element) -> Driver<Element> {
asDriver { _ in .just(value) }
}
}
asDriverOnErrorJustComplete()
ViewModel Output โ UI ๋ฐ์ธ๋ฉ ์ ์ค๋ฅ ๋ฌด์
asDriver(onErrorJustReturn:)
๋คํธ์ํฌ ์คํจ ์ Placeholder ๋ฐ์ดํฐ ์ ๋ฌ
2๏ธโฃ map / filter ๊ณ์ด Sugar
extension ObservableType {
/// ๋ชจ๋ ์์๋ฅผ Void๋ก ๋ณํ (๊ฐ์ด ํ์ ์์ ๋)
func mapToVoid() -> Observable<Void> { map { _ in } }
}
extension Observable where Element: OptionalType {
/// nil ์ ํํฐ๋งํ๊ณ ๋ํ์ ๋ฒ๊ฒจ๋ธ๋ค (Optional ์ ๊ฑฐ)
func filterNil() -> Observable<Element.Wrapped> {
compactMap { $0.asOptional }
}
}
OptionalType
ํ๋กํ ์ฝ์associatedtype Wrapped
์var asOptional: Wrapped?
๋ก ์ ์ ํ ์ฌ์ฉ.
3๏ธโฃ ControlEvent ํธ์
extension ControlEvent where Element == Void {
/// ๋ฒํผ ์ฐํ ๋ฐฉ์ง: ๊ธฐ๋ณธ 300ms ์ฐ๋กํ
func throttleTap(_ interval: RxTimeInterval = .milliseconds(300)) -> ControlEvent<Void> {
throttle(interval, scheduler: MainScheduler.instance)
}
}
button.rx.tap.throttleTap()
์ผ๋ก ๊ฐ๋จ ์ ์ฉ
4๏ธโฃ Subject / Relay Helper
import RxRelay
extension PublishRelay {
/// ํ์ฌ ์ฐ๋ ๋์์ ์์ ํ๊ฒ onNext (Main ์ฌ๋ถ ์ ํ)
func acceptOnMain(_ element: Element) {
if Thread.isMainThread {
accept(element)
} else {
DispatchQueue.main.async { self.accept(element) }
}
}
}
5๏ธโฃ Disposable & DisposeBag
extension Disposable {
/// DisposeBag ์ด ์๋ ์งง์ ์ค์ฝํ์์ ์ฌ์ฉํ๊ธฐ ์ํ Auto-dispose
func disposed(by bag: inout [Disposable]) {
bag.append(self)
}
}
var tempBag: [Disposable] = []
observable.subscribe().disposed(by: &tempBag)
6๏ธโฃ withUnretained Sugar (iOS 13 ์ดํ ์ง์)
extension ObservableType {
/// RxSwift 6 ์ withUnretained ๋ฅผ iOS 12 ํ๋ก์ ํธ์์๋ ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ shim.
func withUnretained<T: AnyObject>(_ owner: T) -> Observable<(T, Element)> {
map { [weak owner] element in
guard let owner = owner else { throw RxError.noElements }
return (owner, element)
}
.catchError { _ in .empty() }
}
}
7๏ธโฃ Mini Quiz (SelfโCheck)
mapToVoid()
์ignoreElements()
์ ์ฐจ์ด๋?Relay ์์
acceptOnMain
์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ผ๊น?asDriver(onErrorJustReturn:)
์ฌ์ฉ ์ ๋ฌดํ ๋ฃจํ๊ฐ ์๊ธธ ์ ์๋ ์๋๋ฆฌ์ค๋?
๋ชจ๋ ํ์ฅ์ Rx ์ค์ฌ ์ผ๋ก ์ฌ๊ตฌ์ฑํ์ต๋๋ค. ํ์์ ๋ฐ๋ผ ํ์ฌ/ํ๋ก์ ํธ์ ๋ง๊ฒ ์ด๋ฆยท๋ค์์คํ์ด์ค๋ฅผ ์กฐ์ ํด ํ์ฉํด ๋ณด์ธ์. ๐
Last updated