LoginSignup
6
2

More than 5 years have passed since last update.

RxSwift 一定間隔で1文字ずつStringを流し込む(入力する)

Last updated at Posted at 2017-10-04

TL;DR

Stringを1文字ずつ一定間隔で、UILabelやUITextViewに流し込みたい。
「1文字ずつ」、「一定間隔で」……、これはRxが得意そうなやつだ。典型的なストリームの問題だ。
そんなこんなで実装例がなかなか見つからなかったので、考えてみました。

できあがりはこちら↓

実装例

下記の例では0.05秒間隔で1文字ずつ流し込んでいきます。

    @IBAction func didTapButton(_ sender: UIButton) {
        label.text = nil

        let lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        let text  = Observable.just(lorem)
        let timer = Observable<Int>.interval(0.05, scheduler: MainScheduler.instance)

        _ = Observable.combineLatest(timer, text)
            .takeWhile { (i, t)  in
                i < t.characters.count
            }
            .flatMapLatest { (i, t) -> Observable<String> in
                let characters = Array(t.characters)
                let character = characters[i]
                return Observable.just("\(character)")
            }
            .subscribe(onNext: { [weak self] (character) in
                let currentText = self?.label.text ?? ""
                self?.label.text = currentText + character
            })
    }

ポイントはtakeWhileです。

iが文字数以上になるとcompletedが呼ばれ、シーケンスがterminateされます。
試しにsubscribe { print($0) }に変えてみるとcompletedが呼ばれているのが確認できます。

next(L)
next(o)
next(r)
// ...
completed
6
2
1

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
6
2