ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RxSwift - combineLatest(), zip() 에 대해서 알아보자.
    Ray Wenderlich/RxSwift 2018. 7. 13. 02:41



    Ch9. Combining operators p.186 - p.190



    combineLatest

    그림을 보고 combineLatest가 어떤 기능을 할 지, 먼저 추측해보자.

    셜록급의 추리가 아니더라도, 어느정도 끄덕하게 될 만큼 직관적이다.

    두 개의 시퀀스가 combineLatest를 만나 하나의 시퀀스가 되었다.

    이 합쳐진 시퀀스는 서브 시퀀스(즉, leftright)에서 이벤트가 발생할 때마다, 이벤트를 발생시킨다.

    합쳐진 시퀀스는 두 서브 시퀀스의 Element를 조합하여 새로운 Element를 전달한다. 


    첫 번째 예제

    우선 두 개의 시퀀스를 준비해보자.

    let left = PublishSubject<String>() 

    let rightPublishSubject<String>()


    combineLatest를 사용하여 하나로 합쳐진 시퀀스를 만들자.

    let observable = Observable

    .combineLatest(left, right, resultSelector: { (lastLeft, lastRight) in 

    "\(lastLeft) \(lastRight)" 

    })


    let disposable = observable.subscribe(onNext: { (string) in print(string) })


    이벤트를 발생시켜 어떤일이 일어나는지 살펴보자. 그리고 dispose!

    print("> Sending a value to Left"

    left.onNext("Hello,"

    print("> Sending a value to Right"

    right.onNext("world"

    print("> Sending another value to Right"

    right.onNext("RxSwift"

    print("> Sending another value to Left"

    left.onNext("Have a good day,")


    disposable.dispose()


    결과는 아래와 같다.

    --- Example of: combineLatest --- 

    > Sending a value to Left 

    > Sending a value to Right 

    Hello, world 

    > Sending another value to Right 

    Hello, RxSwift 

    > Sending another value to Left 

    Have a good day, RxSwift


    1.

    두 개의 시퀀스를 combineLatest를 사용하여 하나의 시퀀스로 만들었다. 

    위 예제에서는 합쳐진 시퀀스가 String타입이지만, 다른 타입으로 변경도 가능하다.

    2.

    예제의 결과에서 볼 수 있듯, 두 시퀀스가 각각 최초 이벤트를 발생 시켜야만 합쳐진 시퀀스에서 이벤트가 발생한다.

    left.onNext("Hello,")코드가 수행되는 시점에서는 아직 right에 어떤 이벤트도 전달되지 않았다. 그래서 print문이 수행되지 않은 것이다.



    combineLatest을 깔끔하게 쓰는 코드 작성 예시

    이렇게 작성하면 아주 깔끔한 코드가 작성가능하다.

    let observable = Observable

    .combineLatest(leftright, { ($0, $1) }

    .filter( !$0.0.isEmpty }



    두 번째 예제

    combineLatest 은 여러 family 메소드가 있다.


    그리고 combineLatest에 전달되는 서브 시퀀스는 서로 다른 타입이어도 상관없다.

    위 예제에서는 Observable<String>과 Observable<String>을 합쳤지만, 타입이 달라도 된다는 것이다.


    코드를 보고 결과를 예상해보자. 

    (사용자가 날짜 표기법을 변경하는 상황을 가정해서 작성된 코드다.)

    let choice : Observable<DateFormatter.Style> = Observable.of(.short, .long) 

    let dates = Observable.of(Date()) 


    let observable = Observable.combineLatest(choice, dates) { (format, when) -> String in 

    let formatter = DateFormatter() 

    formatter.dateStyle = format 


    return formatter.string(from: when) 

    observable.subscribe(onNext: { value in print(value) })


    결과는 아래와 같다.

    --- Example of: combine user choice and value --- 

    7/13/18 

    July 13, 2018



    combineLatest에 시퀀스를 컬렉션으로 전달하기

    위 그림에 빨간색 화살표가 가리키는 메소드를 보자.

    파라미터를 컬렉션으로 받고 있다.


    그리고 첫 번째 예제에서 사용했던 코드를 잠시 보자.

    let observable = Observable.combineLatest(leftright, resultSelector: { (lastLeft, lastRight) in 

    "\(lastLeft) \(lastRight)" 

    })


    위 코드는 아래처럼 변경할 수 있다.

    let observable = Observable.combineLatest([leftright]) { strings in strings.joined(separator: ") }


    다만, 컬렉션으로 파라미터를 전달할 때는 시퀀스의 타입이 같아야 한다.



    zip을 알아보자. combineLatest와 유사한 듯 다르다. 

    먼저 그림을 통해서 알아보자.


    뭔가 combineLatest와 굉장히 유사하다. 하지만 분명히 다른 점이 있다.


    코드를 작성해보자.

    enum Weather { case cloudy, sunny }


    let left: Observable < Weather > = Observable.of(.sunny, .cloudy, .cloudy, .sunny) 

    let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")


    let observable = Observable

    .zip(left, right, resultSelector: { (weather, city) in 

    return "It's \(weather) in \(city)."

    })


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


    결과는 아래와 같다.

    --- Example of: zip --- 

    It's sunny in Lisbon. 

    It's cloudy in Copenhagen. 

    It's cloudy in London. 

    It's sunny in Madrid.


    zip이 어떻게 작동했는지 살펴보자.

    1. leftright를 하나로 합쳐주었다.

    2. leftright가 각각 이벤트를 하나씩 발생시킬 때까지 기다렸다.

    3. 발생한 이벤트를 조합하여 print문이 수행되었다.


    뭔가 combineLatest와 굉장히! 유사하다. 하지만 어떤 차이점이 있어보이는가?

    combineLatest도 서브시퀀스 모두 첫 이벤트를 발생시켜야 했다. 

    하지만 그 뒤에는 하나의 시퀀스에서만 이벤트가 발생해도 클로져가 수행되었다.


    하지만 이번엔 다르다.

    두 시퀀스에서 항상 새로운 이벤트가 발생되어야 print문이 수행되고 있다.

    그 것이 combineLatest와의 차이이다.

    (원문: They wait until each of the inner observables emits a new value.)

    댓글 1

Designed by Tistory.