サイバーエージェントが主催しております、 「CA.swift #15 WWDC21報告会」が2021年7月14日に開催されました!
今回の CA.swift はイベントタイトルにもある通り、 先日開催された WWDC の内容に関する勉強会となります。今回は以下3つに関しての発表が行われました。
発表内容
- Actorへの第一歩(深見 龍一)
- 検証 SharePlay media playback(行木 千春)
- アクセシブルなチャートを実現しよう(横山 新)
「Actor への第一歩」
深見 龍一(@ryu1sazae)(株式会社 AbemaTV)
Swift 5.5 の目玉である、Swift Concurrency の一要素である Actor についての発表です。
並行処理でmutable state を共有する難しさ
mutable な state を共有する難しさとして、 WWDC のセッションで言及のあった data race を挙げ、どのような不整合を起こすのかの説明です。
上述の mutable な state を同期的に扱うことができればこの不整合は起こらないはずで、その方法は Swift5.4 まででもいくつかあるものの、適切に扱うことが難しいことから、 Actor が登場しました。
Actor
Actor は自身の mutable な state を data race から守るための型です。
Dispatch Queue を用いた書き方と比較し、どのくらい書きやすく、直感的に書けるようになったのかの紹介です。
Actor isolation
Actor isolation とは、Actor が自身の mutable な state を data race から守る仕組みのことです。 Actor-isolated キーワードを用いて Actor の state に安全にアクセスすることができます。
Actor-isolated な宣言の仕方は以下が挙げられます
- デフォルトで Actor-isolated な宣言
- stored properties
- computed properties
- subscripts
- methods
- 関数の引数に対して isolated キーワードをつける
逆に、 Non-Actor-isolated な宣言の仕方は以下が挙げられます
- static な宣言
- インスタンスとは関係をもたず、型自身に紐づくため。
- nonisolated キーワードがついた宣言
Actor-isolated な宣言を使う上での制約は以下が挙げられます
- Actor-isolated な宣言内では同じインスタンスの Actor-isolated な宣言を同期的に呼び出すことができる
- Actor-isolated な宣言を Non-Actor-isolated な宣言から呼び出す場合は、非同期で呼び出さなければならない
- Actor の mutable な state は Actor-isolated な宣言の中で
self.
経由でしか変更できない
cross-actor reference
Actor の外から Actor-isolated な宣言を参照する方法です。
- immutable な状態への参照
Actor の初期化後に値が変更されることがないため、Actor の外からでも同期的に参照可能 - 非同期で Actor-isolated な宣言を参照
- 関数等の参照
- 非同期で呼び出す
- mutable な state の参照
- Read のみ許されており、書き込みはできない
図解した例はこちらです。
Protocol conformances to Actor
既存の protocol に対して Actor をどう組み合わせていくのかについてです。
これまで Swift を書いているのと同じ感覚で protocol に準拠させるとコンパイルエラーとなってしまいます。
例えば Hashable
に準拠させる場合。 Hashable
は準拠先に同期的に関数を定義することを求めているため、 nonisolated
キーワードをつけることにより、実装することができます。
Actor reentrancy
Actor reentrancy とは、Actor-isolated な処理が suspend されると、再開するまでその Actor の他のプログラムを実行する仕組みのことです。
この機能のおかげて Actor は deadlock や不必要な Blocking をされることなくタスクを実行できます。
まとめ
- Actorで状態管理をすると、data race を避けられる
- Actor isolationのおかげで、間違った状態管理をすると、コンパイラが叱ってくれる
- Actor reentrancyにより、dead lockや不必要なblockingなく処理を実行できる
- Actorを使っても、状態の不整合は生じ得るので注意しよう
この記事では具体的な実装コードの解説箇所を省略しています。詳しくは以下のスライドをご覧ください。
「検証 SharePlay media playback」
行木 千春(@Ridwy)(株式会社 AbemaTV)
タイトルにあるようにSharePlayについて発表です。
SharePlayとはFaceTime通話中に離れた相手と同じ体験を共有できる機能です。動画や音楽、アプリ独自の体験を共有することができます。この機能はiOS 15, tvOS 15, macOS 12, Safari 15のいずれもそのバージョンまたはそれ以降でのみ利用できます。
SharePlayは再配信ではなく、コンテンツ自体はこれまで通り各サービスの仕組みで配信し、再生タイミングをコントロールするものです。
Group Activities APIを利用し、FaceTimeを開始したのち、共有する時にはGroupSessionが作成されます。そこにそれぞれのユーザーがジョインする形になります。再生タイミングの同期はAVPlaybackCoordinatorが再生や停止、シークなどのやりとりを代わりにやってくれます。HTTP Live Streamingを同期する場合は EXT-X-PROGRAM-DATE-TIME タグをプレイリストに記述することで可能です。またアプリ独自の体験をシェアする場合はGroupSessionMessangerを利用することで可能です。
この機能を利用する上で気になる点をいくつか確認しています!
- Q. アプリを持っていなかったら?
参加するためのボタンがApp Store導線になり、アプリをインストールできます。
- Q. 非対応のデバイスを持っているメンバーがいたら?(iOS 15未満のiPhoneなど)
SharePlay可能ですが、非対応端末側では特に何も起きず、FaceTime通話が続くだけです。
- Q. 字幕や音声は?
あくまで調整されるのは再生タイミング。各自が設定したい字幕や音声を選択することができます。
- Q. 広告あり・なしのユーザーが混在してたらどうするべき?
パーソナライズされた広告はメインのコンテンツの同期に影響しないように別プレイヤーで再生し広告が終了した時に合流します。
- Q. 同期の精度は?
新OSリリース前の検証となりますが、コントロールイベントの遅延はあまり感じられなかったです。コンテンツの同期の精度はサービスの実装に左右されます。また検証時にはTVアプリでは数フレーム〜数秒のズレが見られました。
所感
- とりあえず組み込みだけなら既存実装を大きく変えることなく可能
- SharePlayを機にインストールしてくれたユーザーがスムーズに視聴できる考える必要がある
- 広告の扱いが難しそう
- Picture-in-Pictureにも対応すると体験としてとても良い
この記事では具体的な実装コードの解説箇所を省略しています。詳しくは以下のスライドをご覧ください。
「アクセシブルなチャートを実現しよう」
横山 新(@BOBG1018Vi)(株式会社 タップル)
Bring accessibility to charts in your appのセッションについての発表です。
アクセシビリティは、障害を持つユーザーなど特定の人を対象するのではなく全てのユーザーに対して必要となってくる要素になります。
実際にiOSアプリのアクセシビリティ対応をするため、
- どのような
accessibilityLabel
が適切だろうか - VoiceOverで実際に読み上げられる文言はどうなっているのだろう
- 色のコントラスト比率を
4.5:1
にして視認性を担保しなくてはいけない
という風に手段から考える人もいるかもしれません。
しかし、まずは手段よりも「なぜそれらが求められているのか」「そもそもアクセシビリティとはどういうところを考えるべきなのか」といった概念から調べることを推奨します。
アクセシビリティの代表的なガイドラインとして、WCAG(Web Content Accessibility Guidelines)というものがあります。
また、WCAGの中で全ての項目は以下の4つに分けることが出来ます。
「知覚可能」にフォーカスしたアクセシビリティ対応の具体例だと、以下のような折れ線グラフにおいて🔼 などのシンボルを追加することで色に頼らない区別の方法を実現するというものがあります。
実装面での気づきに関しては、
- 画面の中に「VoiceOverなどの対応を行いたいFrame」がどこにあるのか容易に取得できるようにしておくと、各Frameに対して楽に設定できます。
- 全ての要素に対して設定を行うのではなく、画面に表示しているViewに対して設定することが推奨されています。
- SwiftUIでのアクセシビリティ対応は、コンポーネント単位での設定がUIKitと比べて容易な印象を持ちました。
Chartsという棒グラフや折れ線グラフを表示することが可能なライブラリがあるのですが、
UIAccessibility.Notification
の設定がすでに行われている- 要素別のlabelやvalueも設定されている
という特徴があるので、導入の検討を行う・参考にしつつ自作するというのが良さそうです。
iOS15からはオーディオグラフという「要素別の読み上げから要約文」までを提供できるVoiceOverのローターが追加されます。
つまり、デベロッパー側がユーザーに対して、どういうところに注目してほしいのか・どのように読んで欲しいのか設定することが出来るため、より良い体験を提供することが出来るようになります。
AXChart
のプロトコルに準拠させて、AXChartDescriptor
を返すだけで対応することが出来ます。
まとめ
- アクセシビリティは全てのユーザーが対象
- コントラスト比を意識しつつ、色に頼らない画面にしましょう
- VoiceOverで取り扱えるようにしましょう
- iOS15からは
AXChartDescriptor
を用いて、オーディオグラフの対応も検討しましょう
今回お話したアプリのコードはGitHubにて公開しておりますので、ぜひお手元で試してみてください。
- https://github.com/ARATAYOKOYAMA/A11yChartApp
- 動作環境:Xcode13 Beta, iOS15
また、Xcodeに付属しているAccessibility Inspector
を活用することでコントラスト比に問題がないか容易に把握することが出来ます。
「どの部分を求めているのか」「どの情報を欲しているのか」ユーザー視点で考え対応していくということを常に心がけていきたいです。
この記事では具体的な実装コードの解説箇所を省略しています。詳しくは以下のスライドをご覧ください。
最後に
今回はWWDC 2021のasync await, SharePlay, アクセシビリティに関して発表してもらいました。
ご興味を持たれた方は弊社のconnpassグループで次回の開催をチェックしていただければと思います。
次回のCA.swiftもお楽しみに!!