RxSwift

[RxSwift] Observable

thoonk: 2021. 2. 16. 16:20
반응형

Observable에 대해서 기록해보겠습니다.

 

공식문서 (ReactiveX)에서는 ObserverObservable을 구독(subscribe)한다.

그리고 그 Observer는 Observable에서 방출(emit)하는 item이나 item의 순서(sequence)에 반응한다. 이러한 패턴은 Observable이 객체를 방출하기를 기다리는 동안 차단할 필요가 없기 때문에 동시 작업(concurrent operations)을 수월하게 하지만 대신 Observable이 미래의 어떤 시간에 적절히 반응할 준비가 되어 있는 관찰자(observer)의 형태로 보초(sentry)를 서게 됩니다.

 

Observable 생명 주기

  1. Create
  2. Subscribe
  3. onNext 
  4. onCompleted or onError
  5. Disposed

Observable가 방출할 수 있는 3가지 이벤트

  • next: 최신(다음) 값(Element)을 방출하는 이벤트
  • error: 방출하다가 에러가 발생하면 error를 방출하고 종료하는 이벤트
  • complete: 성공적으로 sequence를 종료하는 이벤트, 더 이상 값을 방출하지 않는다. 
/// Represents a sequence event.
///
/// Sequence grammar: 
/// **next\* (error | completed)**
@frozen public enum Event<Element> {
    /// Next element is produced.
    case next(Element)

    /// Sequence terminated with an error.
    case error(Swift.Error)

    /// Sequence completed successfully.
    case completed
}

Observable 생성

.create()

아래의 예와 같이 Observable을 생성한다.

let source : Observable = Observable<Int>.create { observer in
    for i in 1...5 {
        observer.on(.next(i))
    }
    observer.on(.completed)

    return Disposables.create {
        print("disposed")
    }
}

source.subscribe {
    print($0)
}
/*
next(1)
next(2)
next(3)
next(4)
next(5)
completed
disposed
*/

 

.just()

하나의 요소를 포함하는 Observable sequence를 생성한다.

let source = Observable.just(1, 2, 3)
source.subscribe {
    print($0)
}
//next((1, 2, 3))
//completed

let source2 = Observable.just([1,2,3])
source2.subscribe {
    print($0)
}
//next([1, 2, 3])
//completed

 

.of()

주어진 값들의 타입추론을 통해 Observable sequence를 생성한다. 

let observable2 = Observable.of(1,2,3)
let observable3 = Observable.of([1,2,3]) // == Observable.just([1,2,3])

 

.from()

array의 요소들을 Observable로 변환하여 하나씩 방출한다. 

let numbers = [1,2,3,4,5]
let source = Observable.from(numbers)
source.subscribe {
    print($0)
}
//next(1)
//next(2)
//next(3)
//next(4)
//next(5)
//completed

 

.empty()

즉시 종료할 수 있는 Observable을 리턴하고 싶을 때 사용한다.  

의도적으로 0개의 값을 가지는 Observable을 리턴하고 싶을 때 사용한다. 

let observable = Observable<Void>.empty()
observable.subscribe(
    
    onNext: { (element) in
        print(element)
    },
    onCompleted: {
        print("Completed")
    })

//Completed

 

.never()

어떤 이벤트도 방출하지 않고 종료되지 않는다. completed되지 않는다. 

let observable = Observable<Any>.never()
     
observable
     .subscribe(
         onNext: { (element) in
             print(element)
     	},
         onCompleted: {
             print("Completed")
     	})

 

.range()

특정 범위를 갖는 Int타입의 sequence를  방출하는 Observable을 생성한다. 

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

observable
    .subscribe(onNext: { (i) in
        let n = Int(i)
        print(n)
    })
/*
1
2
3
4
5
6
7
8
9
10
*/

 


Observable 구독(Subscribe)

Observable는 기본적으로 Subscribe 메서드를 이용해서 구독하고 관찰되어진다.

-> 즉, Observable은 그냥 sequence 정의일 뿐이고 구독되기 전에는 아무런 이벤트를 보내지 않는다.

 

.subscribe()

비동기로 이벤트를 보낼 때 사용하고 결과를 신경쓰지 않는다.

let one = 1
let two = 2
let three = 3

let observable = Observable.of(one, two, three)
observable.subscribe({ (event) in
    print(event)
})
 
/* 
next(1)
next(2)
next(3)
completed
*/

 

.subscribe(onNext:)

.next 이벤트만을 처리하고 error, completed 이벤트들은 무시한다. 

결과를 받아서 처리할 때 사용한다.

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

observable.subscribe(onNext: { (element) in
	print(element)
})
 
/* 
1
2
3
*/

Observable Disposing

Observable에 대한 구독을 취소하여 수동적으로 종료시킬 수 있다.

 

.dispose()

아래의 코드에서 .of()에 무한한 요소가 있다면 completed되지 않기 때문에 dispose()를 이용해서 종료시킨다.

let observable = Observable.of(1,2,3)
let subscription = observable.subscribe({ (event) in
    print(event)
})
subscription.dispose()

 

Disposebag() 

DisposeBag()을 이용하여 여러 구독을 한 번에 종료시킬 수 있다. 

let bag = DisposeBag()

let observable = Observable.of(1,2,3)
let subscription = observable.subscribe({ (event) in
    print(event)
})
subscription.disposed(by: bag)

DisposeBag()의 활용 예시로는 아래의 코드와 같이 사용할 수 있다. 

bag을 다시 초기화함으로써 종료시킬 수 있다. 

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    bag = DisposeBag()
}

 

부족한 부분은 피드백해주시면 감사하겠습니다🙃

 

참고:

github.com/fimuxd/RxSwift/blob/master/Lectures/02_Observables/Ch2.%20Observables.md

github.com/iamchiwon/RxSwift_In_4_Hours

반응형