RxSwift

Observable

motosw3600 2022. 2. 7. 19:30

Observable

  • Observable이란 여러 이벤트들을 생성(emit) 할 수 있는 대상(발행자, Publisher)
  • Observable타입을 이용해서 관찰 가능한 흐름이 생성. 즉 Observable타입을 이용해서 관찰하고 들어온 값을 처리
  • Observer(구독자) Observable(발행자)를 구독하는 형태
  • Observe결과 이벤트 스트림을 Sequence라고도 칭함

Observable의 이벤트

  • next: 항목을 계속 방출하는 기능. 즉 이 이벤트를 받아서 원하는 형태로 처리.

  • complete: 성공적으로 next이벤트가 완료되었을 때, complete 이벤트가 발생. 이벤트 발생 후 스트림 종료

  • error: 값을 발행하다 에러가 발생한 경우 error이벤트를 발생하고 스트림 종료

Observable 생성(emit)

just

오직 하나의 Element만 포함하는 Observable Sequence생성

 

let observable: Observable<Int> = Observable<Int>.just(1)
let observable: Observable<String> = Observable<String>.just("1")

of

가변적인 element를 포함하는 Observable Sequence를 생성

 

let observable: Observable<Int> = Observable<Int>.of(1,2,3,4,5)

 

Array가 인자로 들어갈 시 단일 요소로 취급

 

let observable: Observable<[Int]> = Observable<[Int]>.of([1, 2, 3]) // 단일 요소
// [1, 2, 3]
let observable: Observable<Int> = Observable<Int>.of(1, 2, 3) // 다중 요소
// 1
// 2
// 3

from

오직 Array의 요소들로 Observable Sequence생성

각 요소들을 하나씩 처리

 

let observable: Observable<Int> = Observable<Int>.from([1,2,3,4,5])
// 1
// 2
// 3
// 4
// 5

empty

요소를 가지지 않는 Observable

empty연산자를 통해 .completed 이벤트만 방출

 

let observable = Observable<Void>.empty()

never

empty와 반대 연산자

Event를 발행하지도 않음

 

let observable = Observable<Any>.never()

create

클로저 형식이며 다양한값(onNext, onCompleted, onError) 생성 가능

Observer에 직접 Event 발행

 

Observable<Int>.create({ (observer) -> Disposable in      
    observer.onNext(3)
    observer.onNext(4)
    observer.onNext(5)
    observer.onCompleted()
        
    return Disposables.create()
})
// 3
// 4
// 5
// Completed

range

start부터 count까지 값의 Observable생성

 

let observable = Observable<Int>.range(start: 1, count: 5)
// 1
// 2
// 3
// 4
// 5

repeatElement

지정된 element를 계속 생성

 

let observable = Observable<Int>.repeatElement(3)
// 3
// 3
// 3
// 3
// ..

interval

지정된 시간에 한번씩 event를 생성

 

// 5초마다 0부터 증가
Observable<Int>.interval(5, scheduler: MainScheduler.instance)
// 0
// 1
// 2
// 3
// 4
// ..

 

 


Observable 구독(subscribe)

subscribe

Observable에서 생성한 이벤트를 구독하는 것

let observable = Observable.of(1, 2, 3)
        
observable.subscribe {
    print($0)
}.dispose()

// next(1)
// next(2)
// next(3)
// completed

observable.subscribe(onNext: {
    print($0)
}).dispose()

// 1
// 2
// 3
Note: subscribe뒤에 파라미터를 명시하지 않으면 onNext, onCompleted, onError를 구분해서 받지 않기 때문에 subscribe() 내부 로직이 onNext일 때만 동작하는 것이 아니라 결괏값을 보면 onCompleted의 경우도 같이 실행시킨다. onCompleted는 해당 구독이 중지될 때 실행된다. (보통 메모리에서 해제될 때 onComplted실행 이때 실행시키는 곳에 참조 문제 발생 가능!!)
결론: subscribe안에 파라미터인 onNext를 구분해서 사용해주는 것이 좋다.

Dispose And Terninate

dispose

dispose는 구독을 취소하여 Observable을 수동으로 종료시킴

 

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

//2 observable 구독
let subscription = observable.subscribe({ num in
    print(num)
})

// 구독 종료
subscription.dispose()

 

subscription의 타입은 Disposable(dispose를 할 수 있는 프로토콜)

dispose()를 호출한 뒤에는 이벤트 발생이 종료된다.

DisposeBag

여러 Disposable들을 모아뒀다가 한 번에 처리 가능

각각의 구독에 대한 이벤트 처리보다 DisposeBag을 사용하여 여러 개의 이벤트를 한 번에 처리

 

let disposeBag = DisposeBag()
     
Observable.of(1, 2, 3).subscribe {
    print($0)
}.disposed(by: disposeBag) 

// 1
// 2
// 3

 

 


Trait

  • Observable보다 좁은 범위의 Observable
  • Trait은 부가적인 옵션으로 사용 가능
  • 코드의 가독성 증가
  • Single, Completable, Maybe존재

Single

  • 항상 한 가지 값 또는 오류 알림 둘 중 하나의 이벤트만 발행한다.
  • .success(value)나 .error이벤트 발행
  • .success(value)는 .next + .completed 이벤트의 결합

Completable

  • .completed나.error를 발행, 값은 발행하지 않는다.
  • 완료 여부를 확인할 때 사용

Maybe

  • Single과 Completable을 섞어논 형태
  • .success(value), .completed, .error를 발행
  • 프로세스의 성공, 실패 여부와 같이 발행된 값을 확인 가능

 

ex) Single예제

 

let disposeBag = DisposeBag()

enum FileReadError: Error {
  case fileNotFound
}
    
func findFilePath(from name: String) -> Single<String> {
  return Single.create(subscribe: { (single) -> Disposable in
      
      guard let path = Bundle.main.path(forResource: name, ofType: "txt") else {
          single(.failure(FileReadError.fileNotFound))
          return Disposables.create()
      }
      
      single(.success(path))
      return Disposables.create()
  })
}

findFilePath(from: "File")
    .subscribe(onSuccess: { (result) in
        print(result)
    }, onError: { (error) in
        print(error)
    })
    
// fileNotFound

'RxSwift' 카테고리의 다른 글

RxFlow  (0) 2022.03.30
RxViewController  (0) 2022.03.03
Operator  (0) 2022.02.09
Subject  (0) 2022.02.08
RxSwift란?  (0) 2022.02.07