(just, of, from)
just
just는 하나의 항목을 방출하는 옵저버블을 생성한다.
이 연산자는 옵저버블타입 프로토콜에 타입 메서드 로 선언되어있다.
파라미터로 하나의 요소를 받아서 옵저버블을 리턴한다.
let element = "😀"
Observable.just(element)
파라미터로 element(문자열)를 전달하면 이 문자열을 방출하는 옵저버블이 생성된다.
let element = "😀"
Observable.just(element)
.subscribe{ event in print(event)}
.disposed(by: disposeBag)
//next(😀)
//completed
Observable.just([1, 2, 3])
.subscribe{ event in print(event)}
.disposed(by: disposeBag)
//next([1, 2, 3])
//completed
just로 생성한 옵저버블은 파라미터로 전달한 요소를 그대로 방출한다.
of
두개 이상의 요소를 방출하는 옵저버블을 만들기 위해 just는 불가능하다. 이 때 사용되는 연산자가 of이다.
파라미터의 값이 가변 파라미터로돼있어서 여러가지 값을 전달할 수 있다.
이 연산자는 옵저버블타입 프로토콜에 타입 메서드 로 선언되어있다.
방출할 요소를 원하는 수만큼 방출할 수 있다.
let apple = "🍏"
let orange = "🍊"
let kiwi = "🥝"
Observable.of(apple, orange, kiwi)
.subscribe{ event in print(event)}
.disposed(by: disposeBag)
//next(🍏)
//next(🍊)
//next(🥝)
//completed
Observable.of([1, 2], [3, 4], [5, 6])
.subscribe{ event in print(event)}
.disposed(by: disposeBag)
//next([1, 2])
//next([3, 4])
//next([5, 6])
//completed
담긴 배열이 하나씩 그대로 방출된다.
옵저버블에 담긴 요소가 그대로 개수만큼 방출된다.
from
이 연산자는 옵저버블타입 프로토콜에 타입 메서드 로 선언되어있다.
첫 번째 파라미터로 배열을 받는다.
리턴형을 보면 배열형식이 아니라 배열에 포함된 요소의 형식이다. 이 연산자는 배열에 포함된 요소를 하나씩 순서대로 방출한다.
또한 sequence 형식을 전달할 수 있는 메서드도 선언되어 있다.
let fruits = ["🍏", "🍎", "🍋", "🍓", "🍇"]
Observable.from(fruits)
.subscribe{ print($0) }
.disposed(by: disposeBag)
//next(🍏)
//next(🍎)
//next(🍋)
//next(🍓)
//next(🍇)
//completed
하나의 요소를 방출하는 옵저버블을 생성한다 = just
두개이상의 요소를 방출해야 한다 = of
just와 of는 배열을 넣으면 배열 그대로 방출
배열요소를 순서대로 하나씩 방출하는 옵저버블을 생성한다 = from
(range, generate)
range 정수로 제한
첫 번째 파라미터에는 시작할 정수를 지정한다. 실수를 지정하면 컴파일 에러가 발생한다.
두번째 파라미터에는 방출할 정수의 수를 지정한다.
시작값에서 1씩 증가하는 count개의 개수를 방출한다.
증가하는 수를 바꾸거나, 감소하는 시퀀스를 만들순 없다. 이런 시퀀스를 만들때는 generate연산자를 사용한다
Observable.range(start: 1, count: 10)
.subscribe{print($0)}
.disposed(by: disposeBag)
//next(1)
//next(2)
//next(3)
//next(4)
//next(5)
//next(6)
//next(7)
//next(8)
//next(9)
//next(10)
//completed
generate 정수 제한 X
이 연산자는 모두 4개의 파라미터를 받는다.
첫 번째 파라미터는 initialState: 시작값을 전달한다. 가장 먼저 방출되는 값을 전달한다.
두 번째 파라미터 condition: true를 리턴하는 경우에만 요소가 방출된다. false를 리턴하면 CompletedEvent를 방출하고 바로 종료된다.
세 번쨰 파라미터 scheduler: 스케쥴러를 전달한다.
네 번째 파라미터 iterate: 값을 바꾸는 코드를 전달한다. 보통 값을 증가시키거나 감소시키는 코드를 전달한다.
10보다 작거나 같은 짝수를 방출하는 코드
Observable.generate(initialState: 0, condition: { $0 <= 10}, iterate: { $0 + 2 })
.subscribe{ print($0) }
.disposed(by: disposeBag)
//next(0)
//next(2)
//next(4)
//next(6)
//next(8)
//next(10)
//completed
증가된 값이 10을 초과하면 condition 조건에 따라서 false가 리턴되고 종료된다.
range와 달리 정수로 제한되지 않는다. 문자열도 가능하다.
let red = "🔴"
let blue = "🔵"
Observable.generate(initialState: red, condition: { $0.count < 15 },
iterate: { $0.count.isMultiple(of: 2) ? $0 + red : $0 + blue })
.subscribe{ print($0) }
.disposed(by: disposeBag)
//next(🔴)
//next(🔴🔵)
//next(🔴🔵🔴)
//next(🔴🔵🔴🔵)
//next(🔴🔵🔴🔵🔴)
//next(🔴🔵🔴🔵🔴🔵)
//next(🔴🔵🔴🔵🔴🔵🔴)
//next(🔴🔵🔴🔵🔴🔵🔴🔵)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴)
//next(🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵🔴🔵)
//completed
repeatElement
동일한 요소를 반복적으로 방출
다른 연산자와 마찬가지로 옵저버블타입 프로토콜의 타입메서드로 선언되어있다.
첫번째 파라미터로 요소를 전달하면 요소를 반복적으로 방출하는 옵저버블을 리턴한다.
반복적이란 뜻은 무한정반복한다는 뜻이다
let element = "❤️"
Observable.repeatElement(element)
.subscribe{ print($0) }
.disposed(by: disposeBag)
//next(❤️)
//next(❤️)
//next(❤️)
//next(❤️)
//next(❤️)
//..무한반복
무한루프로 끊임없이 방출된다.
이 메서드로 옵저버블을 생성할때에는 방출되는 요소의 개수를 제한하는 것이 정말 중요하다 (take)
deferred
이 연산자를 활용하면 특정 조건에 따라서 옵저버블을 생성할 수 있다.
이 연산자는 옵저버블을 리턴하는 클로저를 파라미터로 받는다.
let factory: Observable<String> = Observable.deferred{
flag.toggle()
if flag{
return Observable.from(animals)
}else{
return Observable.from(fruits)
}
}
형식을 지정해주지 않으면 deferred에서 형식을 알 수 없다는 오류가 뜬다.
리턴하는 옵저버블의 형식을 지정해야한다.
create
다른 연산자들은 파라미터로 전달된 요소를 방출하는 옵저버블을 생성한다. 이렇게 생성된 옵저버블은 모든 요소를 방출하고 CompletedEvent를 방출하고 종료된다. 이게 옵저버블의 기본 동작이기 때문에 앞에서 공부한 연산자로는 동작을 바꿀 수 없다.
옵저버블이 동작하는 방식을 직접 구현하고 싶다면 create연산자를 사용한다.
이 연산자에는 옵저버를 파라미터로 받아서 Disposable을 리턴하는 클로저를 전달한다.
URL에서 html을 다운로드한 다음에 문자열을 방출하는 옵저버블을 구현
create메서드로 옵저버블을 직접 구현할 때에는 몇가지 기본적인 규칙을 지켜야 한다.
1. 요소를 방출할때엔 onNext메서드를 사용하고, 방출할 요소를 전달한다.
2. 옵저버블은 요소를 방출할수도 안할수도있다 onNext를 반드시 호출해야하는건 아니다.
3. 옵저버블이 종료되기 위해서는 onError || onNext를 반드시 호출해야한다.
옵저버블 중엔 영원히 종료되지 않는 경우도 있는데, 이런 경우가 아니라면 둘중 하나는 반드시 호출해야 한다.
let disposeBag = DisposeBag()
enum MyError: Error {
case error
}
Observable<String>.create{ (observer) -> Disposable in
guard let url = URL(string: "https://www.apple.com")
else{
//잘못된 url이면 종료해야하므로 여기서 종료해야함
//오류가 발생했으므로 ErrorEvent를 전달해야함.
//여기서 사용된 observer는 클로저로 전달된 파라미터
//MyError는 위에서 생성
//return형식은 꼭 Disposables.create() s중요
observer.onError(MyError.error)
return Disposables.create()
}
guard let html = try? String(contentsOf: url, encoding: .utf8) else{
observer.onError(MyError.error)
return Disposables.create()
}
//여기까지 실행됐다면 문자열을 잘 가져온 것이고 옵저버로 전달하면 된다.
//문자열을 방출한다
observer.onNext(html)
//옵저버블이 정상적으로 종료되는것만 구현하면 된다.
observer.onCompleted()
return Disposables.create()
}
.subscribe{ print($0) }
.disposed(by: disposeBag)
(empty, error)
두 연산자가 생성한 옵저버블은 NextEvent를 전달하지 않는다는 공통점이 있다.
다시말해 어떠한 요소도 방출하지 않는다.
empty
이 연산자는 CompletedEvent만 방출하는 옵저버블을 생성한다.
요소를 방출하지 않기때문에 요소의 형식은 중요하지 않다. 보통은 Void로 선언한다.
empty연산자는 파라미터가 없다.
let disposeBag = DisposeBag()
Observable<Void>.empty()
.subscribe{ print($0) }
.disposed(by: disposeBag)
//completed
CompletedEvent만 방출하고 종료된다.
이 연산자는 옵저버가 아무런 동작없이 종료해야할때 자주 활용된다.
error
이 연산자는 ErrorEvent만 방출하는 옵저버블을 생성한다.
Error를 처리할 때 주로 활용된다.
요소를 방출하지 않기때문에 요소의 형식은 중요하지 않다. 보통은 Void로 선언한다.
empty연산자는 파라미터로 Error를 받는다.
enum MyError: Error {
case error
}
Observable.error(MyError.error)
.subscribe{ print($0) }
.disposed(by: disposeBag)
//Unhandled error happened: error