Platforms State of the Union 書き起こし(SwiftUIのみ)

Platforms State of the Union - WWDC 2019で語られたSwiftUIの部分を書き起こします。

Developer Productivity Platforms Core Technologies

デベロッパーの生産性についての話。
優秀なツールは生産性を劇的に向上させる。時間に余裕ができて、よりよいアプリケーションが作れる。その土台がプログラミング言語です。
この5年でSwiftは成熟し、全プラットフォームに組み込まれ、SwiftUIの基礎になりました。Xcodeはエディターとデバッカーではなく、必要なものすべてが入っている。
継続したテストをサポートしたり、機械学習や拡張現実などの新しい技術を試す様々なツールも提供する。そして新たなフレームワークSwiftUiがUIの構築に革命をもたらす。
Swift、Xcode、SwiftUIの3つの要素で生産性のレベルが格段に上がり、アプリケーションの作り方が一新される。

SwiftUI

SwiftUIは新しいUIフレームワークです。
Swiftでゼロから作られました。
コードを減らし、よりよいコードが書けるようなり、Apple全プラットフォームで利用できます。
一行のコードに多くの機能が組み込まれており、大幅に書く量がへります。

SwiftUIでのレイアウトの要点は3つ。

まずビューの構成とレイアウトを定義する。
次に表示する画像とテキストのビューを作る。
最後に見た目を調整するパラメーターと修飾子。

具体的にコードをみていきましょう。

スクロールリストのコードは単純です。
リストを宣言し、各行のモデルオブジェクトを記述するだけ。

設定もコールバックもありません。

上の画像表示も単純です。
画像を丸くクリップし、影を足すだけ

Image(name)
    .clipShape(Circle())
    .shadow(radius: 3, y: 3)

シンプルでより優れたコードになります。

APIは明確な記述が正解になるように設計されています。

このラベルの作成もそのまま書けば正しいコードになり、ダークモードなどをサポートします。
文字列補間も完全にローカライズ可能です。
これらにより、様々なエラーが防げます。このリストではモデルチェンジが行われると各行が自動でアップデートされ古いデータは表示されません。
それに読みやすい。

この画像のコードにはcornerRadiusが3とある。

Image(item.image)
    .cornerRadius(3)

読むだけでインターフェイスがわかるのです。

どのプラットフォームか関係なく、このコードはどこででも再利用することができます。

(従来は)ローレベルグラフィックスや合成コードは共有できましたが、ハイレベルなUIコードはできませんでした。
でもSwiftUIは共有の幅を広げました。

もちろんプラットフォームごとにアプリケーションが使いやすいようにUIのカスタマイズは必要です。でもSwiftUIのAPIならパターンを覚えれば何にでも使えてネイティブなUIが実現できる。

SwiftUIの4つの原則

SwiftUIは4つの原則で設計しました。

まず宣言型シンタックス(Declarative)
画面をどう変更したいかではなく、何を表示したいかに注目します。

例えばグレーのHeadlineフォントでラベルを作るとき、それを実現するプロセスは何段階もありとても複雑です。
しかし何がほしいかなら単純です。

テキストの内容は「done」。Headlineフォントで色はグレー。
SwiftUIはそれをそのまま書かせてくれます。

Text("done")
    .font(.headline)
    .color(.gray)

最低限のコードですべてを表せるのです。

反復も迅速になります。
ラベルをボタンに変えるのも1行ですみます。

Button("done", action: done)
    .font(.headline)
    .color(.gray)

2つ目の原則はできる限り自動機能を提供すること(Automatic)

大量のコードを自分で書かずに済みます。

このアプリケーションはシンプルですが、多くの自動機能が含まれています。
デフォルトでのスペースやセーフエリアの調整、右横書き言語へのレイアウト対応。Dynamic Typeやダークモードなども最小限の記述で済みます。

少ないコードで多くの自動機能を実現します。

さらにもう一つ、注目すべき重大な機能があります。

現代のUIはアニメーションが多いですが、SwiftUIなら同じ宣言で、自動的にアニメーション化されます。

1行のコードで全階層でアニメーションが有効になり、準備もクリーンアップも不要です。
Keynoteのマジックムーブのようにかんたんでさらにパワフルです。
追加や削除されたビューもどう遷移するかを1行で指定できます。

.transition(.offset(size))

アニメーション中もアプリケーションは常にインタラクティブな状態のままです。
アニメーション中にユーザーが別の場所に移動してもSwiftUIが自動で対応してくれます。

3つ目の原則は組み合わせ可能なAPIが学習と反復を簡単にすることです(Compositional)

個別ビューの宣言を見てきましたが、複雑なビューも簡単です。
小さなピースを組み立てるだけ。

VStack(alignment: .leading) {
    Text(item.title)
    Text(item.subtitle)
}

HStackやVStackを組み合わせるだけでパワフルなレイアウトが簡単に作れます。

また修飾子をつかってビューのプロパティも組み合わせることができます。

修飾子はどんなビューにも適用できます。
例えばこのcolorです。

.color(.gray)

このようにビューや修飾子を組み合わせて圧倒的にパワフルなUIを作ることができます。

最後の原則は常にUIの一貫性を保つことです(Consistent)

UIは常にアプリケーションのデータと同期しているべきです。
以前はエラーが起こりがちでしたが、SwiftUIならデータ変更のたび自動でUIが更新されます。
データが更新される場所は主に2つ。

片方がモデルオブジェクト。

新しいBindableObjectプロトコルに適合させれば既存のものを使えます。

最新だとBindObject? WWDCから変わったと思うので後で確認

データがいつ変わるか指定するだけです。

もう片方はUIの状態。

@State var editing = true

例えばビューが編集モードかどうか、プロパティの@Stateというラッパーで宣言されます。
どのビューのプロパティも変更可能ですが、SwiftUIを使えばアプリケーションが必要とする変更の少なさに驚くでしょう。

モデルや状態が変わるとUIが自動的に更新されます。

しかもすべてSwiftコードなので宣言の中で直接モデルオブジェクトが使えて値の変換やフォーマットも回り道せずにできます。

例えばこの文字列補間で日付をローカライズされたテキストにできます。

Text("\(alarm.date, formatter: formatter)")

SwiftUIなら少ないコードでUIの一貫性を実現できます。

以上が4つの原則です。

  1. Declarative(宣言的シンタックス)
  2. Automatic(自動機能)
  3. Compositional(組み合わせ可能なAPI)
  4. Consistent(一貫性のあるUIの状態)

Xcode

Xcode内にSwiftUIのワークフローを作りました。
パワフルで柔軟なコードと使いやすく迅速な反復が可能なUIツールが融合。
これからはどちらかを選ぶ必要はありません。

既存のソースコードで使えるので素早い開発が可能になります。

ライブで見ればわかってもらえるでしょう。

--- Demo ----

ハイキングアプリケーションのTableViewCellにビューを追加し、トレイルの難易度を示すとします。

ライブラリのテキストをドラックすればXcodeがレイアウトを提案してくれて、場所を指定すればレイアウトを編集してくれます。

次にプロパティを編集します。

command + クリックでインスペクタを表示させます。

テキストを小さくします。

コードを見ていてください。
自動で書いてくれました。

ソースエディタでコードを編集しても同じことができます。

Xcodeがコードを自動でビルドし、右の画面が更新されました。

どこからでもデザインツールにアクセスできます。

VStackからインスペクタを開いて、プロパティを変更します。とてもスピーディですね。

このビューにはタイトルや難易度などがありますが、どのデータをプレビューに表示すべきでしょうか?

デザインしているデータを表示させるのに苦労してきました。
そこでプレビューを発明しました。

プレビューの説明をします。

スクロールして、アプリケーション内のこの短いコードのデザインを表示するのがプレビューです。

自分のアプリケーション内なので全コードにアクセスでき、チームのみんなとも共有できます。

ダークモードでも見られます。

プレビュー固有の修飾子もあります。

デフォルトではデバイスのサイズですが、TableViewCellの作業でコンテンツのサイズに合わせられます。

.previewLayout(.sizeThatFits)

プレビューの利点はいくつも作れることです。

違うデータで2つ目のプレビューを追加してみましょう。

そしてさらにcommand + クリックでrepeateを選びます。

Dynamic Typeに共通のサイズを列挙しそれらを使いセルを設定します。

これでダークモードや各種サイズのセルが同時に確認できます。

セルをタップして詳細を出したい。

ファイルを見てみましょう。

トレイルの場所を名前から判断すると痛い目を見ます。

なので詳細ビューの画像はなるべく大きくするのが重要です。

SwiftUIで作ったものがあります。

バナーをタップすると拡大表示するようにしたい。

再生ボタンを押すだけでそのテストができます。
プレビューがインタラクティブになります。

クリックしてそれぞれの拡大表示をテストできます。

表示にアニメーションをつけるのも簡単です。

表示を変える記述をwithAnimationブロックでラップすると美しいアニメーションが付きます。

カスタマイズも簡単です。エフェクトをドラマティックにしてみましょう。

withAnimation(.basic(duration: 2.0)) {
    self.expanded.toggle()
    }
}

もっと素敵になりましたね。

アニメーションはキャンセルもリバースも可能でアニメーションは常に反応する状態です。

TableViewCellと詳細ビューをまとめてみましょう。

画面をトレイルのリストのビューに切り替えましょう。

実際のデバイスでどう見えるかが知りたい。

ボタン一つでXcodeがプロジェクトをビルドインストールしてプレビューを起動します。

ちゃんと操作できます。

ではビルドしたセルを使って見ましょう。

ここをTrailCellに変更すると、トレイルが表示されます。

タップで詳細に切り替えるのもSwiftUIならとても簡単です。

NavigationButtoでラップすると詳細ビューに移れる。

スノークリークをタップしてみましょう。

画像を開きます。雪が深く、難易度が高い。楽ではなさそうです。

コード一つでスワイプで削除する機能を追加。
行きたくない山を削除できます。

最後にダークモードを見てみましょう。

こうして簡単にプレビューがダークモードになります。

どう操作したのかがビデオで確認できなかった

バレーフロアーをタップしてズーム。週末を楽しめそうですね。

Dynamic Typeサイズやダークモードなど様々なデータを実際のデバイスでテストできました。

自分でビルドせずにです。

楽しいでしょ?

デバックや変更、検索がしやすいツールで、直接コードを編集できるので柔軟に作業できます。

どのOSにも対応しており、どのプラットフォームでもネイティブなアプリケーションが作れます。

パフォーマンスでも動きでも他のアプリケーションに負けません。

自分のペースで適用できます。

適用するのはビュー1つでもアプリケーション全体でもいい。

既存のUIKitやAppKitのコードとも合うので書き直す必要はありません。

早くなれてもらうために、新しいドキュメントも開発し、プロジェクトの作成から段階を追ってUIの作成を支援します。

すぐに慣れるはず。

これがSwiftUIと新しいツールです。