Observable은 RxSwift의 기본이 되는 개념으로, sequence라고도 한다.
예를 들어 iOS 애플리케이션에서 사용자가 탭을 세 번 하면 세 개의 이벤트가 순차적으로 발생될 것이고, 이 이벤트는 언젠가 종료될 것이다.
하지만 어느 순간 에러가 발생해서 이벤트가 완전히 종료되기 전에 프로그램이 종료된다면..??!! 😱
그래서 이벤트들을 구독하자!!는 것이 Observable의 개념이다. Observable을 구독하면 이벤트들의 값이 변할 때마다 이 사실을 알 수 있게 된다.
let observable = Observable.just(1)
let observable2 = Observable.of(1, 2, 3) // Observable<Int>
let observable3 = Observable.of([1, 2, 3]) // Observable<[Int]>
let observable4 = Observable.from([1, 2, 3, 4, 5]) // Observable<[Int]>
observable2
와 observable3
의 자료형 차이 주목!! observable2는 개별적인 값, observable3은 배열을 저장하고 있음of()
에 배열을 넣으면 배열 자체가 하나의 항목으로 방출되지만, from()
을 사용하면 배열의 요소들이 순서대로 방출된다!!observable4.subscribe { event in
print(event)
}
Observable을 구독(subscribe)해서 Observable이 가지고 있는 값에 접근할 수 있다.
subscribe
는 실제 값을 가지고 있는 게 아니라 이벤트를 전달해준다. (이벤트, 다음 이벤트, 다음 값, 그 다음 이벤트, 그 다음 값…)
next(1)
next(2)
next(3)
next(4)
next(5)
completed
위 코드를 실행해보면 다음과 같은 결과가 나온다. 실제 저장된 값이 아닌 이벤트가 출력되는 것을 볼 수 있다!
또한 Observable의 모든 값을 출력하고 나면 completed
라는 이벤트가 발생된다.
observable4.subscribe { event in
if let element = event.element {
print(element)
}
}
element
라는 프로퍼티를 사용하면 실제 값에 접근할 수 있다.
observable.subscribe(onNext: { element in
print(element)
})
위 방법은 옵셔널 언래핑도 해줘야 하고 귀찮으니까..!!! onNext
를 사용하면 더 쉽게 값에 접근할 수 있다.
// 결과
1
2
3
4
5
subscription을 생성하면 subscriber가 리턴되는데, 이 subscriber는 특정 시퀀스를 관찰(observe)하고 있다.
언젠가 이 subscriber를 사용하지 않게 되면 이 구독을 해제해주어야 한다. 이를 dispose라고 함! 구독을 해제해주지 않으면 메모리 누수 같은 문제가 발생할 수 있기 때문에 꼭 dispose를 해주어야 한다. 🤯
let subscription = observable.subscribe(onNext: { element in
print(element)
})
subscription.dispose()
dispose()
라는 메소드를 사용해서 dispose를 해줄 수 있다. 하지만 위와 같이 subscription과 dispose를 따로따로 해주면 어느 시점에 dispose를 해줘야 할지 알기 어렵다.
let disposeBag = DisposeBag()
Observable.of("A", "B", "C")
.subscribe {
print($0)
}
.disposed(by: disposeBag)
그래서 위처럼 subscribe와 disposed 메소드를 이어서 작성해주면 observable가 종료되는 시점에 dispose가 잘 실행될 수 있다.
여기서 DisposeBag
은 이름 그대로 disposable을 담은 가방이다. Dispose 해야 하는 리소스들이 많으면 일일이 dispose()
메소드를 호출해서 구독 해제를 시켜줘야 하는데 너무 귀찮고 번거로우니까!! DisposeBag에 담아주면 이 DisposeBag이 알아서 dispose()
메소드를 호출해준다.
RxSwift) Dispose /Disposable / DisposeBag 이해하기
Observable<String>.create { observer in
observer.onNext("A")
observer.onCompleted()
observer.onNext("?")
return Disposables.create()
}.subscribe(onNext: { print($0) }, onError: { print($0) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") })
.disposed(by: disposeBag)
create
메소드를 사용하면 onNext
, onCompleted
, onError
같은 메소드를 클로저 안에서 직접 호출할 수 있다.
A
Completed
Disposed
이때 onCompleted나 onError가 호출되면 Observable이 dispose 된다. 그래서 위 코드를 실행해보면 onCompleted 다음에 있는 observer.onNext("?")
는 방출이 되지 않는다.