Help us understand the problem. What is going on with this article?

自分の Combine 101 ノート

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

原則

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

練習したいもの

主にはこちらです:

  • @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% おすすめです!

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

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

vc7
iOS Developer from 🇹🇼
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした