take연산자는 여러가지 버전이 있다.
take
take는 정수를 파라미터로 받아서 해당 숫자만큼만 이벤트를 방출한다.
let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Observable.from(numbers)
.take(5)
.subscribe{print($0)}
.disposed(by: disposeBag)
//next(1)
//next(2)
//next(3)
//next(4)
//next(5)
//completed
take로 전달된 5개만 방출한다
take연산자는 NextEvent이외엔 관여하지 않아서 마지막에 CompletedEvent || ErrorEvent를 전달한다.
takeuntill
takeuntill는 두가지 버전이 있다.
1. 옵저버블을 받는 takeuntill
옵저버블을 파라미터로 받는다.
파라미터로 전달받은 옵저버블에서 NextEvent를 방출하기 전까지 원본 옵저버블에서 NextEvent를 전달한다
let subject = PublishSubject<Int>()
let trigger = PublishSubject<Int>()
subject.take(until: trigger)
.subscribe{print($0)}
.disposed(by: disposeBag)
subject.onNext(1)
subject.onNext(2)
//next(1)
//next(2)
아직 트리거가 이벤트를 방출하지 않았기 때문에 이벤트가 방출된다.
let subject = PublishSubject<Int>()
let trigger = PublishSubject<Int>()
subject.take(until: trigger)
.subscribe{print($0)}
.disposed(by: disposeBag)
subject.onNext(1)
subject.onNext(2)
trigger.onNext(0)
subject.onNext(3)
//next(1)
//next(2)
//completed
그래서 트리거가 방출되면 CompletedEvent가 방출되고 다시 subject에서 NextEvent를 방출하더라도 실행은 되지만 방출되진 않는다.
2. predicate를 받는 takeuntill
첫 번째 파라미터는 옵저버블이 방출하는 요소를 받아서 Bool을 리턴하는 클로저다.
이 클로저에서 false를 리턴하는동안 이벤트를 방출하고 true를 리턴하면 이벤트 방출을 종료하고 옵저버블을 종료한다.
두번째 파라미터는 takewhile과 같다.
subject.take(until: { $0 > 5 })
.subscribe{print($0)}
.disposed(by: disposeBag)
subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
subject.onNext(5)
subject.onNext(6)
//next(1)
//next(2)
//next(3)
//next(5)
//completed
만약 true가 되면 이벤트 방출을 종료하고 옵저버블을 종료한다.
이후에 false를 리턴하는 값을 다시 전달해도 더이상 이벤트를 전달하지 않는다
takewhile
이 연산자는 클로저를 파라미터로 받아서 predicate로 사용한다. 여기서 true를 리턴하면 구독자에게 전달한다.
다시말해 nextevent를 전달한다.
연산자가 방출하는 이벤트는 조건을 충족하는 이벤트까지만 방출한다.
두 번째 behavior파라미터는 마지막에 확인한 값을 방출할지 말지 결정한다.
기본값은 exclusive로 선언되어있고, 마지막에 확인한 값이 true에 해당한다면 방출하지만 나머지 경우에는 무시한다.
이 값을 inclusive로 바꾸면 마지막에 확인한 값이 false여도 방출한다.
let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Observable.from(numbers)
.take(while: { !$0.isMultiple(of: 2) })
.subscribe{ print($0) }
.disposed(by: disposeBag)
//next(1)
//completed
조건은 홀수다.
그렇기 때문에 2는 짝수기때문에 1까지만을 방출하고 completedEvent가 방출되고 종료된다.
3은 홀수지만 이미 옵저버블이 종료되었기 때문에 방출되지 않는다.
takeLast
takeLast는 정수를 받아서 옵저버블을 리턴한다.
원본 옵저버블이 방출하는 이벤트 중에서 마지막에 방출하는 넥스트이벤트의 파라미터로 지정한 숫자만큼 방출한다.
이 연산자의 가장 중요한점은 구독자에게 전달되는 시점이 지연된다는 것이다.
let subject = PublishSubject<Int>()
subject.takeLast(2)
.subscribe{ print($0) }
.disposed(by: disposeBag)
(1...10).forEach{subject.onNext($0)}
1에서 10까지 옵저버블로 전달이 되었지만 아무것도 실행되지 않는다.
아직 옵저버블이 종료될지 안될지 모르기 때문이다.(마지막이 바뀔 수 있다)
그러다 옵저버블에서 CompletedEvent가 실행되면 이때 버퍼에 저장해둔 이벤트를 방출하고 종료한다.
let subject = PublishSubject<Int>()
subject.takeLast(2)
.subscribe{ print($0) }
.disposed(by: disposeBag)
(1...10).forEach{subject.onNext($0)}
subject.onCompleted()
//next(9)
//next(10)
//completed
takefor
let o = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
o.subscribe { print($0) }
.disposed(by: disposeBag)
//1초마다
//next(0)
//next(1)
//...무한정
여기에 takefor연산자를 추가한다.
takefor는 두개의 파라미터를 받는데 scheduler는 일단 무시.
duration은 timeInterval을 전달한다. 옵저버블이 이벤트 방출을 시작하면 여기에서 전달한 시간만큼 이벤트를 전달하고 시간이 경과하면
더이상 이벤트를 전달하지 않고 끝낸다.
let o = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
o.take(for: .seconds(3), scheduler: MainScheduler.instance)
.subscribe { print($0) }
.disposed(by: disposeBag)
//next(0)
//next(1)
//completed
0과 1을 방출하고 completedevent를 방출한다.
3초를 전달했기 때문에 2까지 전달되어야 하지만 시간상의 오차가 존재하기 때문에 1까지 전달하고 끝낸다.