[RxSwift] Observable이란 - (2)

728x90
반응형

 

 

Observable의 개념에 대해 알아 보겠습니다.

 

Observable이란

observable, observable sequence, sequence라는 표현을 쓰는데 사실 다 같은 말입니다.
중요한것은 이벤트가 비동기적으로 생성하는 기능 이라는것이고, 계속해서 이벤트를 생성하는데 이러한 과정을 Emit이라고 합니다.
또한 각각의 이벤트들은 숫자나 커스텀한 인스턴스등과 같은 값을 가질 수 있고, 또는 탭과 같은 제스처일 수도 있습니다.

 

1. Observable의 생명주기

세 개의 구성요소를 확인 할 수 있다
Observable에는 next, completed, error로 구성되어 있습니다.

  • next 이벤트를 통해 각각의 요소들을 방출.

  • 세 번의 tap 이벤트를 방출한 뒤 이벤트들이 다 방출되면 완전 종료.
  •  completed이벤트가 발생.

  • 1, 2를 방출하고 에러가 발생해 error를 통해 종료.
public enum Event<Element> {
  /// Next elemet is produced.
  case next(Element)
 	
  /// Sequence terminated with an error.
  case error(Swift.Error)
 	
  /// Sequence completed successfully.
  case completed
 }
  • .next 이벤트는 어떠한 Element 인스턴스를 가지고 있는 것을 확인할 수 있다.
  • .error 이벤트는 Swift.Error 인스턴스를 가진다.
  • completed 이벤트는 아무런 인스턴스를 가지지 않고 단순히 이벤트를 종료시킨다.

 

 

2. Observable의 생성

 

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)

element가 많다고해서 배열이 아니고 타입을 보시면 Int타입입니다. 가변적으로 element들을 넣을 수 있습니다.

인자로 Array를 넣게 되면 단일 요소로 가지게 됩니다. 타입은 Observable<[Int]>

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

 

from

array의 요소들로 Observable Sequence 생성
타입은 Observable <Int> 이고 오직 Array만 취합니다.

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()

Observable은 반드시 특정 타입으로 정의되어야 하는데 타입 추론을 할 수 없으므로 Void는 적절한 타입.

 

never

empty와는 반대로 never연산자가 있습니다.
never는 이벤트를 방출 조차 하지 않습니다.

let observable = Observable<Any>.never()

 

range

start 부터 count크기 만큼의 값을 갖는 Observable을 생성한다.

let observable = Observable<Int>.range(start: 3, count: 6)
//3
//4
//5
//6
//7
//8

 

repeatElement

지정된 element를 계속 Emit 한다.

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

//3
//3
//3
//3
//3
.
.
.

위의 코드는 3초마다 0부터 숫자가 증가하게 된다.

 

 

create

Observer에 직접 Event를 방출합니다.

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

//print
3
4
5
Completed

 

 

 

3. Observable 구독

Observable은 실제로 sequence 정의일 뿐이다. Observable은 구독되기 전에는 아무런 이벤트도 보내지 않습니다. 즉 위의 예제 코드들은 subscribe되기 전까진 값이 실행되지 않았을 것입니다.

 

위의 Observable 생성 코드들에 대해 subscribe 해보겠습니다.

 

subscribe

let observable = Observable<Int>.range(start: 3, count: 6)
observable.subscribe(onNext: { (element) in
  print(element)
 })

// print
3
4
5
6
7
8
completed

 

 

4. Disposing and Terninating

dispose()

disposing은 구독을 취소하여 Observable을 수동적으로 종료시킨다.

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

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

subscription.dispose()
  1. Int 타입의 Observable을 생성
  2. 이 Observable을 구독. 여기서는 subscripe를 이용해 Disposable을 리턴하도록 한다.

 

여기서 구독을 취소하고 싶으면 dispose()를 호출하면 된다. 구독을 취소하거나 dispose 한 뒤에는 이벤트 방출이 정지되겠죠?

 

DisposeBag()

각각의 구독에 대해서 일일히 관리하는 것은 효율적이지 못하기 때문에, RxSwift에서 제공하는 DisposedBag 타입을 이용할 수 있습니다.
즉, Disposable 들을 모아놨다가 한번에 처분하는 방식 입니다.

 

// 1
  let disposeBag = DisposeBag()
     
// 2
  Observable.of("A", "B", "C")
  .subscribe{
    print($0)
  }
  .disposed(by: disposeBag) // 3
  1. 한번에 모아서 처리할 dispose bag을 만들어줍니다.
  2. observable을 만든다
  3. subscribe로부터 방출된 리턴 값을 disposeBag에 추가한다.

 

observable에 대해 subscribing 하고 이 것을 즉시 dispose bag에 추가하는 방식의 패턴으로 자주 사용하시게 될것입니다.

 

5. Trait

Trait은 일반적인 Observable보다 좁은 범위의 Observable

사실 Observable만 사용해도 됩니다. 즉, Trait은 옵션으로 사용할 수 있습니다.
하지만 Trait의 사용 목적은 코드의 가독성을 높일 수 있습니다.

 

종류 : Single, May, Completable

 

Single

Single은 Obvservable의 한 형태이지만, Observable처럼 존재하지 않는 곳에서부터 무한대까지의 임이의 연속된 값들을 배출하는 것과는 달리, 항상 한 가지 값 또는 오류 알림 둘 중 하나만 배출한다.

 

Single은 .success(value) .error 이벤트를 방출 합니다.
.success(value)는 .next + .completed 이벤트의 결합이라고 볼 수 있습니다.

 

예를들어 한가지 프로세스인 데이터 다운로드의 로직에서 사용할 수 있겠죠

 

 

Completable

Completable은 .completed .error를 방출 하고, 어떠한 값을 방출 하진 않습니다!

연산이 성공적으로 완료되었는지 확인하고 싶을 때 사용합니다.

 

 

Maybe

Maybe는 Single 과 Completable을 섞어 놓은 형태이고,
.success(value) , .completed , .error 를 방출합니다.
프로세스가 성공, 실패 여부와 더불어 출력된 값도 방출 할 수 있습니다.

 

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(.error(FileReadError.fileNotFound))
          return Disposables.create()
      }
      
      single(.success(path))
      return Disposables.create()
  })
}

findFilePath(from: "김승진")
  .subscribe(onSuccess: { (result) in
      print(result)
  }, onError: { (error) in
      print(error)
  })

 

반응형

'RxSwift' 카테고리의 다른 글

[RxSwift] filter vs skip operator  (0) 2019.09.14
[RxSwift] Subject와 Relay - (3)  (0) 2019.07.25
[RxSwift] RxSwift의 기본 개념 - (1)  (0) 2019.07.25