Observable

SteadySlower·2022년 3월 4일
0

RxSwift

목록 보기
2/7
post-thumbnail

이번 포스팅에는 Observable을 직접 구현하고 구독해보겠습니다!

구현하기

기본

가장 기본적으로 구현하는 방법은 3가지가 있습니다.

먼저 just를 사용하면 1개의 event만 발행합니다.

of는 여러 개의 인자를 받아서 모두 event로 발행합니다.

from의 경우에는 배열을 받아서 배열 요소들을 발행합니다.

import RxSwift

let observable = Observable.just("하나만")
let observable2 = Observable.of("여", "러", "개")
let observable3 = Observable.from(["배", "열", "에", "서"])

참고로 위 Observable들은 모든 String을 발행하기 때문에 Observable 타입이 됩니다.

직접 구현

위처럼 데이터만 전달하면 자동으로 구현되도록 하지 않고 임의로 직접 구현할 수도 있습니다.

Observable이 발행하는 데이터의 타입을 선언하고 create라는 메소드를 사용합니다. 이 메소드에는 클로저를 하나 전달하는데 그 클로저는 AnyObserver 타입의 인자를 받습니다. 해당 인자를 통해서 onNext로 발행하고 onComplete로 complete하면 됩니다.

그리고 해당 클로저는 반드시 Disposable을 반환해야 합니다.

let observable = Observable<String>.create { observer in
    observer.onNext("직")
    observer.onNext("접")
    observer.onNext("구")
    observer.onNext("현")
    observer.onCompleted()
    return Disposables.create() // Disposable을 반환
}

구독하기

event

구독은 기본적으로 subscribe 메소드에 클로저를 전달해서 할 수 있습니다. 해당 클로저는 event를 인자로 받습니다.

출력된 내용을 보면 발행되는 String 데이터가 onNext라는 이벤트에 싸여 출력되는 것을 볼 수 있습니다. 즉 정확히 얘기하면 Observable은 String을 발행하는 것이 아니라 Event 객체를 발행하는 것입니다.

그리고 모든 발행을 마치면 completed라는 이벤트를 발행합니다.

let observable = Observable.from(["배", "열", "에", "서"])

observable.subscribe { event in
    print(event)
}

//🖨 출력 결과
next()
next()
next()
next()
completed

element

이벤트 안에 있는 String만 출력하고 싶다면 아래 처럼 event의 element라는 property를 출력하면 됩니다.

다만 이 경우에는 Optional로 싸여있습니다. 또한 complete 이벤트에는 element가 없으니까 nil이 출력되게 됩니다.

observable.subscribe { event in
    print(event.element)
}

//🖨 출력 결과
Optional("배")
Optional("열")
Optional("에")
Optional("서")
nil

unwrapping해서 출력한 결과도 한번 보겠습니다.

observable.subscribe { event in
    guard let element = event.element else { return }
    print(element)
}

//🖨 출력 결과
배
열
에
서

onNext

하지만 이런 식으로 unwrapping하는 코드를 매번 넣는 것은 귀찮은 일입니다. 우리가 Observable을 구독할 때는 대부분 Event 객체가 아니라 안에 있는 데이터가 필요한 경우가 대부분 입니다.

따라서 클로저를 바로 전달하지 않고 onNext라는 인자에 전달하면 바로 element에 접근할 수 있습니다.

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

//🖨 출력 결과
배
열
에
서

onComplete

complete 이벤트가 발생할 때 실행할 클로저를 전달하는 인자도 있습니다. complete 이벤트는 Observable이 발행을 마쳤을 때 1번 발생합니다.

onCompleted에 전달하는 클로저는 인자를 받지 않습니다. (() → Void)

observable.subscribe(
    onNext: { element in print(element) },
    onCompleted: { print("발행 끝") }
)

//🖨 출력 결과
배
열
에
서
발행 끝

Dispose

dispose는 구독을 메모리에서 해제하는 작업입니다. Observable이 complete를 발행하고 발행을 마쳤다고 구독 객체가 자동으로 메모리에서 해제되는 것은 아닙니다. dispose()를 통해 직접 메모리에서 해제 해주어야 합니다.

observable
    .subscribe(
        onNext: { element in print(element) },
        onCompleted: { print("발행 끝") })
    .dispose()

disposeBag

DisposeBag은 dispose를 전담하는 객체입니다. 구독 객체에 등록해놓으면 dispose를 알아서 해줍니다.

let disposeBag = DisposeBag()

observable
    .subscribe(
        onNext: { element in print(element) },
        onCompleted: { print("발행 끝") })
    .disposed(by: disposeBag)

onDisposed

dispose될 때 실행되는 코드를 정의할 수도 있습니다. onCompleted와 마찬가지로 인자가 없는 클로저입니다.

observable
    .subscribe(
        onNext: { element in print(element) },
        onCompleted: { print("발행 끝") },
        onDisposed: { print("dispose 됨") })
    .disposed(by: disposeBag)

//🖨 출력 결과
배
열
에
서
발행 끝
dispose됨
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글