LoginSignup
4
3

More than 5 years have passed since last update.

ReactiveSwiftを克服する: Property (Part 5)

Last updated at Posted at 2018-11-14

この記事について

この記事はConquering ReactiveSwift: Property (Part 5)の翻訳です。

以下本文です。

ReactiveSwiftを克服する: Property (Part 5)

ReactiveSwiftを克服するシリーズのパート5へようこそ。前回の記事では、SignalProducerを生成、start、監視する方法を学びました。この記事では、PropertyとMutablePropertyという考え方について議論していきましょう。

定義

Propertyは監視可能なコンテナで、値が変わるたびに値を排出します。PropertyProtocolに準拠していて、PropertyProtocolは次のようなプロパティを持ちます:

  • value: 現在の値を表します。
  • producer: 現在の値と、それに続く値を送るSignalProducerです。Propertyが破棄されたり、これ以上変更がない場合は、SignalProducerも完了し、それ以降値を送りません。
  • signal: 以降に続く値を送るSignalです。現在の値は送りません。Propertyが破棄されたり、これ以上変更がない場合は、SignalProducerも完了し、それ以降値を送りません。

なぜ便利なのか?

値だけを扱い、エラーのことは考えない場合に便利です。
前回の記事の例を考えてみましょう。

50秒の間、5秒に一度の間隔で経過時間を出力しなさい。

これに対して私たちは次のようなSignalProducerを用意しました。

let signalProducer: SignalProducer<Int, NoError> = SignalProducer { (observer, lifetime) in
    let now = DispatchTime.now()
    for index in 0..<10 {
        let timeElapsed = index * 5
        DispatchQueue.main.asyncAfter(deadline: now + Double(timeElapsed)) {
            guard !lifetime.hasEnded else {
                observer.sendInterrupted()
                return
            }
            observer.send(value: timeElapsed)
            if index == 9 {
                observer.sendCompleted()
            }
        }
    }
}

ここのエラー型にあたるNoErrorの意味は、エラーの処理が必要がないことを表していることに注意してください。このような例は、Propertyの良い使いどころです。

それでは、Propertyを定義してみましょう。

let property = Property(initial: 0, then: signalProducer)

ここで、初期値は0でそれに続く値がsignalProducerによって返される値です。

さきほど書いた通り、Propertyにはsignalproducerというプロパティがあり、両方とも監視することができます。しかし、両者の重要な違いは、signalは現在値を排出せず、それに続く値のみを排出することです。

property.producer.startWithValues { value in
    print("[Observing SignalProducer] Time elapsed = \(value)")
}

/* 出力:
[Observing SignalProducer] Time elapsed = 0
[Observing SignalProducer] Time elapsed = 0
[Observing SignalProducer] Time elapsed = 5
[Observing SignalProducer] Time elapsed = 10
[Observing SignalProducer] Time elapsed = 15
[Observing SignalProducer] Time elapsed = 20
[Observing SignalProducer] Time elapsed = 25
[Observing SignalProducer] Time elapsed = 30
[Observing SignalProducer] Time elapsed = 45
[Observing SignalProducer] Time elapsed = 35
[Observing SignalProducer] Time elapsed = 40
*/
property.signal.observeValues { value in
    print("[Observing Signal] Time elapsed = \(value)")
}

/* 出力
[Observing Signal] Time elapsed = 0
[Observing Signal] Time elapsed = 5
[Observing Signal] Time elapsed = 10
[Observing Signal] Time elapsed = 15
[Observing Signal] Time elapsed = 20
[Observing Signal] Time elapsed = 25
[Observing Signal] Time elapsed = 30
[Observing Signal] Time elapsed = 35
[Observing Signal] Time elapsed = 40
[Observing Signal] Time elapsed = 45
*/

この例では、SignalProducerからの値を受け取るPropertyを生成しました。Signalからの値を受け取るPropertyも生成することも可能です。

MutableProperty

MutablePropertyは、Propertyと同じく、監視可能なコンテナです。しかし、値を直接変更することができる点が異なります。PropertyProtcolに準拠しているのはPropertyと同じです。

MutablePropertyは初期値だけで初期化することができます:

let mutableProperty = MutableProperty(1)

値の変更はこうします:

mutableProperty.value = 3

MutablePropertyのsignalproducerはPropertyと同じように監視可能です。

MutablePropertyの便利な使い方はバインディングです。MutablePropertyを使うと以下のように書けます:

mutableProperty <~ signalProducer

このコードだと、mutablePropertyvaluesignalProducerによって決まります。

まとめ

この記事でPropertyとMutablePropertyについてわかってもらえたら嬉しいです。サンプルコードはこちらにあります。次回の記事では、Signalの高度な制御を可能にしてくれるActionについて紹介します。

シリーズ内リンク集

  1. ReactiveSwiftを克服する: 導入 (Part 1)
  2. ReactiveSwiftを克服する: 基本要素 (Part 2)
  3. ReactiveSwiftを克服する: SignalとObserver (Part 3)
  4. ReactiveSwiftを克服する: SignalProducer (Part 4)
  5. この記事です
  6. ReactiveSwiftを克服する: Action (Part 6)
4
3
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
4
3