12
8

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.

自分の Combine 101 ノート

Last updated at Posted at 2020-04-19

このビデオに話したものを基き、練習しようと思います。

原則

練習する内容はなるべく設計を考えず、最小限、単純にしようと思います。

練習したいもの

主にはこちらです:

  • @Published
  • .eraseToAnyPublisher()
  • .flatMap
  • Future
  • sink

などなど

環境

  • Xcode - Version 11.4 (11E146)
  • Playground

RxSwift 経験者。

はじめ

こちらのクラスをベースにやっていこうと思います。

import UIKit
import Combine

class Article {
    @Published var title: String = ""
}
  • @Published という property wrapper をつければ publisher になれるということです。

title の変化を購読する

まあ、購読は RxSwift 由来の呼び方なんですけどw

プロパティを publisher 化した後、その publisher をアクセスしたいときに、プロパティ名の前に $ するだけでおっけ (便利! :tada:

let article = Article()

// これだけで済む
let publisher = article.$title

Cancellable と sink

ここはまず購読のみでつかちゃいます。

let cancelable = publisher.sink { print($0) }

そして、その下にこの行を追加したら

article.title = "New Title"

console にはこのようになります。

""
"New Title"

ブロックしないと最初の値も出てきてますね、そしてこうすればひとまずなんとかなります!

let cancelable = publisher
    .dropFirst()
    .sink { print($0) }

output

"New Title"

AnyPublisher にする

.eraseToAnyPublisher() はくそ長いので抵抗はややある(笑)
けど、今の段階しょうがないですね

let doubleLengthPublisher = article.$title
    .map { $0 + $0 }
    .eraseToAnyPublisher()

明示的に型を素直に書いておいても良い:

let doubleLengthPublisher: AnyPublisher<String, Never> = article.$title
    .map { $0 + $0 }
    .eraseToAnyPublisher()

Never ってなんやねん

RxSwift の経験者として、これを初めてみたときこれはなんだっけ全然わからなかった笑

定義から見て Publisher の protocol に OutputFailure の二つの associatedtype が定義されています。

Never を Failure のところに入れたら、この Publisher からエラーが出てくるわけはないと表明するになります。

このような設定は UI 向けの interface に向いてるなと思っています。

flatMap と Future を加えてみましょう

  • flatMap の用途は、主にエラーによるストリームの途絶えを防ぐためのもの(正式にゆうと operator ですね)です。

  • Future - promise を使って、ストリームを作る。非同期の処理を combine のストリームにするツールです。

さて、コードを書きましょう

let isTitleValid = article.$title
    .dropFirst()
    .flatMap { title in
        return Future { promise in
            DispatchQueue.main.async {
                promise(.success(title.count > 4))
            }
        }
     }
     .eraseToAnyPublisher()

型推論はちゃんとできているのは驚いていたところです。

不安だとしたら、明示的に書いておいても良いと思います。

そして沈んでおいて:

let cancellable = isTitleValid.sink { print($0 ? "valid" : "not valid") }

値を変化してみて

article.title = "a"
article.title = "over 4"

間違いなければ console はこうなるはずです。

not valid
valid

所感

RxSwift とはかなり似てると思われていますが、練習するとき RxSwift で積んできたくせを一旦忘れておいてから Combine はよりスムーズできるなと思います。(個人差あり)

そして wwdc2019#721 はとても素晴らしい資料です。合成(composition) など、 RxMarbles で見ることができないところ、 Apple 社はちゃんそれらへんを可視化してきてるのでとても分かりやすかったと思うんで 100% おすすめです!

次のステップはもっと使いこなして画面に組み込んでみたいですね。
さて、今回はここで終わりたいと思います

また次回!(あったら笑)

12
8
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
12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?