SwiftUI関連のアップデートによってさらにレイアウトが簡単に
このセクションでは、SwiftUIのアップデートやデータを簡単に表示するためのAPIについて紹介します。宣言的UIを可能にしたフレームワークSwiftUIはファーストリリースから今回が3回目のリリースとなりました。今回のSwiftUIのアップデートでは、さらにSwiftUIがアプリ開発に採用されるようになる事を目指しています。AppleはSwiftUIを使ってApple Payの購入フローUIやiOSに予めインストールされている天気予報アプリをリプレイスしており、新しいSwiftUIの実用性の高さが伺えます。
またWhat's new in SwiftUIではデータフォーマッタの新しいAPIも紹介されており、SwiftUIに留まらない簡単にUIを構築するためのアップデートが行われていることがわかります。
Swift Conccurrencyのサポート
新登場のAPIの中には非同期処理に関する強力なサポートが多くあります。その全てがSwift ConcurrencyのAPIを活用しており、Swiftらしくかつ簡潔に非同期的に更新されるUIを記述できます。
まずは、AsyncImageです。AsyncImageを使うと与えたURLから非同期に画像を取得し、取得した画像を描画します。URLから画像データをダウンロードしてImageに渡すまでの処理を省略できるので便利です。さらに、非同期処理で画像を取得している間はプレースホルダーが自動で挿入されます。
次に、task modifierが登場しました。task modifierを使うことによって、Viewが表示されたイベントをフックして非同期処理を実行することができます。また、この非同期処理はViewが取り除かれた際に自動でキャンセルされます。
Listのアップデート
SwiftUIのListのカスタマイズ性がさらに向上しました。
まず、待望のPull to Refleshの機能が登場しました。UIKitではPull to RefleshはUIRefreshControlをrefreshControlプロパティに与えることによって実現しています。SwiftUIではListからrefreshable modifierを呼び出す事が可能になり、Listの上部をPullする事とその際に実行する処理を記述できるようになります。下図の例を見ると画面の上部にUIRefreshControlのようなコンポーネントが表示されている事がわかります。
次に、Listに並べられたCellに対してSwipe actionの設定が可能となりました。この設定によって、Cellの端をスワイプすることによって任意の操作が可能なコンポーネントをCellの端から出現させる事ができます。これは、UIKitではtableView(_:trailingSwipeActionsConfigurationForRowAt:)やtableView(_:leadingSwipeActionsConfigurationForRowAt:)の実装によって実現していたものです。UIKitではSwipe actionを使って表示させるUIの設定値をDelegateメソッドを実装し返却するように実装していましたが、SwiftUIではListの実装とSwipe actionの実装が近いためより直感的になっていると感じました。
Textのアップデート
Textのフォーマットやローカライズに関して便利なアップデートがありました。文字列に対する操作や文字列をパースして表示を切り替える処理は、アルゴリズムや抽象化の方法を考えるのが面倒なため、標準APIが提供してくれるのは有り難いです。
まず、TextがMarkdownに従った文字列を受け取ると、それをパースし表示してくれるようになりました。
さらに独自にMarkdown文字列のデコード方法を定義し、Markdown文字列内の特定の部分に独自のスタイルを当てることができます。例えば、下図の例ではHelloという文字列に対してカラフルなスタイルを当てています。Web上でMarkdwonエディターを提供しコンテンツを作成できる機能を持つサービスではDB上にMarkdown情報を保存したり、独自のスタイルを定義しているケースがあると思います。そのようなサービスにて大活躍しそうな機能です。
文字列のフォーマットが非常に簡単になりました。まずは、時間のフォーマットです。今まではDateFormatterを使ってタイムスタンプを表現したData型をString型に変換していました。今回のアップデートでは、DateFormatterを介さずにString型への変換が可能となるインタフェースがいくつか追加されました。
Date型にString型へのフォーマットを行うインタフェースを加える取り組みは、既にOSS(SwiftData)でいくつか行われており、今まで一定の需要がありました。公式から同様の機能が提供されると、外部依存を減らす事ができて良いですね。
また、日付だけではなく人名に関するフォーマットAPIも追加されました。このAPIを使うと「ファーストネームだけを表示する」「複数の人名をandを使って接続する」というフォーマットが可能となります。このような機能は独自に実装すると、思わぬエッジケースによって不具合を呼んだり、抽象化や管理場所を考えるのが面倒だったりするので、公式から提供されるのは嬉しいです。
Buttonのアップデート
アプリ内でよく使うButtonのコンポーネントにもアップデートがありました。下記画像中にあるような、丸みを帯びた美しいデザインのButtonが標準APIを使うことによって、簡単に作れるようになりました。
方法はbuttonStyle modifierに対して.bordered
を与えるだけです。この指定をすることによって、初期状態のButtonと異なり丸みを帯びたデザインになります。tintColorや他のmodifierと組み合わせる事によってさらに見た目をカスタマイズすることができます。
例えば、controlSize modifierを使えば下記のようなButtonを簡単に作り出せます。単に大きな表示になっているだけではなく、丸みを帯びたデザインになっている事がわかると思います。
さらにこれらのButton Styleに適応した場合、自動的にButtonのDisable、ダークモード、およびアクセシビリティのデザインが設定されます。ほんの少しの記述によってここまで網羅的にデザインが適応されるのは意図しない表示にならないか不安になる一方で、UI実装が効率的に進められる印象を持ちました。
おわりに
連載第3回となる今回ではXcode Cloud、およびSwiftUIについてWWDC21にて発表されていた内容をまとめました。
iOS開発者として近年の発表を聴講していると、今まで外部に依存していた機能をApple公式のものに置き換えられるようになっていると感じます(例えば、RxSwiftをCombineに、CocoaPodsをSwift Package Managerに)。
これはiOS開発環境を変える強力なアップデートが年々増えていることを表しており、Swift ConcurrencyやXcode Cloudもその1つになると思います。また、SwiftUIは年々できる事が増えており、その継続的な進化には驚かされます。さらに、Apple公式アプリ以外にもSwiftUIを採用した事例も多く聞くようになっています。
次回はiOS/iPadOSに新たに追加された機能や変更点について解説します。お楽しみに。