RxSwift Ch2

33395 단어 rxswiftrxswift

RxSwift 스터디 GitHub 를 보고 하나씩 따라하는 곳입니다

Ch2 Observable

Observable이란?

  • 비동기적으로 관찰가능한 이벤트를 방출하는 객체를 말한다

Observable 만들기

just, of, from

let ob1 = Observable.just(1)
let ob2 = Observable.of(1,2,3)
let ob3 = Observable.from([1,2,3])

Observable 구독

위의 옵져버블을 선언하는걸로는 아무일도 일어나지 않습니다.
무조건 구독을 해줘야, 방출하는 값을 받을 수 있음!

subscribe()

let ob1 = Observable.just(1)

ob1.subscribe({ event in
    if let element = event.element {
        print(element)
    }
})

//1

subscribe(onNext: )

let ob2 = Observable.of(1,2,3)

ob2.subscribe(onNext: { (element) in
    print(element)
})

/*
1
2
3
*/

.empty()

completed 이벤트를 전달하고 바로 종료

let ob = Observable<Void>.empty()

ob.subscribe(onNext: { (element) in
    print(element)
}, onCompleted: {
    print("Completed")
})

//Completed

.never()

아무런 이벤트를 전달하지 않음

let ob = Observable<Void>.never()

ob.subscribe(onNext: { (element) in
    print(element)
}, onCompleted: {
    print("Completed")
})

.range()

let ob = Observable<Int>.range(start: 1, count: 10)

ob.subscribe(onNext: { (element) in
    print(element)
})

/*
1
2
3
4
5
6
7
8
9
10
*/

Disposing과 종료

각각의 구독을 관리를 해줘야 하는데, dispose()를 명시적으로 호출하는 방법이 있지만 권장되지 않는다(비효율, 휴먼 에러)

let bag = DisposeBag() 이라는 변수를 하나 선언해서, 모든 구독의 끝에 .disposed(by: disposeBag) 을 호출하면, 모두 bag에 담아놓았다가, 해당 bag이 선언된 부분이 해제될때 한꺼번에 해제시켜준다.

Create

직접 Observable을 customgkrp Create해줄수도 있습니다

let disposeBag = DisposeBag()

let ob = Observable<String>.create { (observer) -> Disposable in
    observer.onNext("1")
    observer.onNext("4")
    observer.onNext("9")
    
    observer.onCompleted()
    
    return Disposables.create()
}

ob.subscribe(onNext: {print($0)},
             onError: {print($0)},
             onCompleted: {print("Complted")},
             onDisposed: {print("Disposed")})
.disposed(by: disposeBag)

Observable factory 만들기

deferred를 이용해서 외부 조건에 영향을 받게 만들 수도 있습니다 :)

import RxSwift

let disposeBag = DisposeBag()

var flip = false

let ob = Observable<Int>.deferred {
    flip.toggle()
    
    if flip {
        return Observable.of(1,2,3)
    } else {
        return Observable.of(4,5,6)
    }
}

for _ in 0...3 {
    ob.subscribe(onNext: {
        print($0, terminator: " ")
    })
    .disposed(by: disposeBag)
    print()
}

/*
1 2 3 
4 5 6 
1 2 3 
4 5 6 
*/

Traits 사용

보다 좁은 범위의 Observable로써 특정 용도에 적절하다

Single

  • success(data) or error 만 방출
  • success(data) (는 next + completed를 의미한다)

아래 예제를 보겠습니다

let bag = DisposeBag()

enum NetworkError: Error {
    case failToConnect
}

func getRequest(url: String?) -> Single<Bool> {
    return Single<Bool>.create { single in
        guard let url = url else {
            single(.failure(NetworkError.failToConnect))
            return Disposables.create()
        }
        
        if url == "https://www.apple.com" {
            single(.success(true))
        } else {
            single(.success(false))
        }
        
        return Disposables.create()
    }
}

getRequest(url: "https://www.apple.com")
    .subscribe(onSuccess: { success in
        print(success)
    },
    onFailure: {error in
        print(error.localizedDescription)
    },
    onDisposed: {
        print("disposed")
    })
    .disposed(by: bag)

약간 Result Type 느낌?

Completable

  • completed or error 만 방출
enum LoadingError: Error {
    case failToLoad
}

let bag = DisposeBag()

func loading(complete: Bool) -> Completable {
    return Completable.create { completable in
        guard complete else {
            completable(.error(LoadingError.failToLoad))
            return Disposables.create()
        }
        
        completable(.completed)
        return Disposables.create()
    }
}

loading(complete: true)
    .subscribe {
        print("completed")
    } onError: { error in
        print(error.localizedDescription)
    }
    .disposed(by: bag)

완료했는지 에러가 났는지 여부만 방출합니다. 값은 x

Maybe

  • success(data), completed, error를 모두 방출
enum LoadingError: Error {
    case failToLoad
}

let bag = DisposeBag()

func study() -> Maybe<String> {
    return Maybe<String>.create { maybe in
        maybe(.success("RxSwift"))
        maybe(.completed)
        maybe(.error(LoadingError.failToLoad))
        
        return Disposables.create()
    }
}

study()
    .subscribe { result in
        switch result {
        case .success(let language):
            print("Study " + language)
        case .completed:
            print("Completed")
        case .error(let error):
            print(error.localizedDescription)
        }
    }
    .disposed(by: bag)

이런느낌?

Challenges

do연산자

특정 이벤트가 발생했을때, 실행되는 콜백함수를 등록하고 싶을때 사용.
발생되는 요소를 수정하지 않고 구독자로 그대로 전달합니다

let bag = DisposeBag()

Observable.of(1,2,3,4,5)
    .do {
        $0 * 10
    }
    .subscribe(onNext: {
        print("sub: ", $0)
    })
    .disposed(by: bag)

debug연산자

let bag = DisposeBag()

let ob = Observable<Any>.never()
    .debug("동작확인")
    .subscribe()
    .disposed(by: bag)
    
// 2022-03-25 18:23:34.315: 동작확인 -> subscribed

좋은 웹페이지 즐겨찾기