0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Combining Operatorsチートシート

Posted at

Combining Operators

RxSwiftでコードを書く必要があり、学習中です。
参考文献を元に学んだ内容をすぐ振り返れるようにまとめていきます。
今回はCombining Operatorsについてまとめました。
完全に自分の解釈でコメントを載せていますが、解釈に誤りがありましたら、コメント欄より教えてください。

startWith()

example(of: "startWith") {
  // 1
  let numbers = Observable.of(2, 3, 4)
  
  // 2
  let observable = numbers.startWith(1)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.42.56 PM.png

Observable.concat

同じ型同士の時のみ、Concatできる!

example(of: "Observable.concat") {
  // 1
  let first = Observable.of(1, 2, 3)
  let second = Observable.of(4, 5, 6)
  
  // 2
  let observable = Observable.concat([first, second])
  
  observable.subscribe(onNext: { value in
    print(value)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.42.47 PM.png

concat

example(of: "concat") {
  let germanCities = Observable.of("Berlin", "Münich", "Frankfurt")
  let spanishCities = Observable.of("Madrid", "Barcelona", "Valencia")
  
  let observable = germanCities.concat(spanishCities)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.42.05 PM.png

concatMap

example(of: "concatMap") {
  // 1
  let sequences = [
    "German cities": Observable.of("Berlin", "Münich", "Frankfurt"),
    "Spanish cities": Observable.of("Madrid", "Barcelona", "Valencia")
  ]

  // 2
  let observable = Observable.of("German cities", "Spanish cities")
    .concatMap { country in sequences[country] ?? .empty() }

  // 3
  _ = observable.subscribe(onNext: { string in
      print(string)
    })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.41.49 PM.png

mege

maxConcurrentを使うことで、同時にObserveするSequenceの上限を設定できる。

example(of: "merge") {
  // 1
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
    
    // 2
    let source = Observable.of(left.asObservable(), right.asObservable())
    
    // 3
    let observable = source.merge(maxConcurrent: 2)
    _ = observable.subscribe(onNext: { value in
      print(value)
    })

    // 4
    var leftValues = ["Berlin", "Munich", "Frankfurt"]
    var rightValues = ["Madrid", "Barcelona", "Valencia"]
    
    repeat {
        switch Bool.random() {
        case true where !leftValues.isEmpty:
            left.onNext("Left:  " + leftValues.removeFirst())
        case false where !rightValues.isEmpty:
            right.onNext("Right: " + rightValues.removeFirst())
        default:
            break
        }
    } while !leftValues.isEmpty || !rightValues.isEmpty

    // 5
    left.onCompleted()
    right.onCompleted()
  }

コンパイル結果

Screen Shot 2020-11-30 at 10.41.22 PM.png

combineLatest

全てのObservableから値が発信されるまで、何もしない。異なる方のSequenceをまとめて、最新の値を取り出す。

example(of: "combineLatest") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()

    // 1
//    let observable = Observable.combineLatest(left, right) {
//      lastLeft, lastRight in
//      "\(lastLeft) \(lastRight)"
//    }
    
// 1   combineLatestでタプルにして、filterをかける方法がよく使われる。
//    let observable = Observable
//      .combineLatest(left, right) { ($0, $1) }
//      .filter { !$0.0.isEmpty }

    
    // 1: Stringが確か受付内ため、余り使われない方法
    let observable = Observable.combineLatest([left, right]) {
      strings in strings.joined(separator: " ")
    }


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

    // 2
    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("Swift")
    print("> Sending another value to Left")
    left.onNext("Have a good day,")

    left.onCompleted()
    right.onCompleted()
  }


コンパイル結果

Screen Shot 2020-11-30 at 10.41.09 PM.png

combine user choice and value

ユーザーの設定が変更した時に、表示値を変える

example(of: "combine user choice and value") {
  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)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.40.52 PM.png

zip

indexed sequencing: ペアが成立しなくなったら、zipは値を発しなくなるが、observableがCompleteするまで処理が終わらないため、observableが完了していることを確認すること。

example(of: "zip") {
  enum Weather {
    case cloudy
    case sunny
  }
    
    let left: Observable<Weather> = Observable.of(.sunny, .cloudy, .cloudy, .sunny, .cloudy)
  let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")

    let observable = Observable.zip(left, right) { weather, city in
      return "It's \(weather) in \(city)"
    }
    _ = observable.subscribe(onNext: { value in
      print(value)
    })
    
  }

コンパイル結果

Screen Shot 2020-11-30 at 10.40.38 PM.png

withLatestFrom

example(of: "withLatestFrom") {
  // 1
  let button = PublishSubject<Void>()
  let textField = PublishSubject<String>()
  
  // 2
//the trigger observableが撮りガー
   let  observable  =  textField.sample(button)
//data Observableがトリガー
//  let observable = button.withLatestFrom(textField)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })

  // 3
    
  textField.onNext("Par")
  textField.onNext("Pari")
  textField.onNext("Paris")
  button.onNext(())
  button.onNext(())
}

コンパイル結果

Screen Shot 2020-11-30 at 10.40.24 PM.png

amb

二つのObservableのどちらをつかうかAmbiguousな場合。 使い所:connecting to redundant servers and sticking with the one that responds first.

example(of: "amb") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  
  // 1
  let observable = left.amb(right)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 2
  left.onNext("Lisbon")
  right.onNext("Copenhagen")
  left.onNext("London")
  left.onNext("Madrid")
  right.onNext("Vienna")
  
  left.onCompleted()
  right.onCompleted()
}

コンパイル結果

Screen Shot 2020-11-30 at 10.40.08 PM.png

switchLatest

example(of: "switchLatest") {
  // 1
  let one = PublishSubject<String>()
  let two = PublishSubject<String>()
  let three = PublishSubject<String>()
  
  let source = PublishSubject<Observable<String>>()

    // 2
    let observable = source.switchLatest()
    let disposable = observable.subscribe(onNext: { value in
      print(value)
    })

    // 3
    source.onNext(one)
    one.onNext("Some text from sequence one")
    two.onNext("Some text from sequence two")
    
    source.onNext(two)
    two.onNext("More text from sequence two")
    one.onNext("and also from sequence one")
    
    source.onNext(three)
    two.onNext("Why don't you see me?")
    one.onNext("I'm alone, help me")
    three.onNext("Hey it's three. I win.")
    
    source.onNext(one)
    one.onNext("Nope. It's me, one!")
    disposable.dispose()
  }

コンパイル結果

Screen Shot 2020-11-30 at 10.39.53 PM.png

reduce

注意:sequencesが完了しないと、Summaryがemitされない。

example(of: "reduce") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  // 1
//  let observable = source.reduce(0, accumulator: +)
    let observable = source.reduce(0){summary, newValue in
        return summary + newValue
    }

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

コンパイル結果

Screen Shot 2020-11-30 at 10.39.33 PM.png

scan

累計、統計、状態をコンピュートする際に使える。

値が変わると毎回、Observableから値がEmitされる。

example(of: "scan") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  let observable = source.scan(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.38.40 PM.png

練習

example(of: "Challeng1") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
    let scanedObservable = source.scan(0, accumulator: +)
    let observable =  Observable.zip(source, scanedObservable){current, total -> String in
        return "Total:\(String(total)), Current:\(String(current)))"
    }
    
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

コンパイル結果

Screen Shot 2020-11-30 at 10.38.28 PM.png

練習

acc(current, accumuratedValue)となるから、acc.1 + currentとしている。

//acc(current, accumuratedValue)となるから、acc.1 + currentとしている。
example(of: "Challeng2") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
    let  observable = source.scan((0, 0)) { acc, current in
        print("acc\(acc)")
        print("current\(current)")
        return (current, acc.1 + current)
    }
    
    _ = observable.subscribe(onNext: { tuple in
        print("Value = \(tuple.0)   Running total = \(tuple.1)")
    })
    
}

コンパイル結果

Screen Shot 2020-11-30 at 10.38.17 PM.png

参考文献

1.Combining Operators Written by Florent Pillet
Chapter9 Transforming Operators Written by Scott Gardner
詳細が気になる方はこちらをご参照ください!
https://www.raywenderlich.com/13285844-rxswift-reactive-programming-with-swift-update-now-available

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?