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