WWDC Quick Look 💓 By SwiftGGTeam
Customize your app for Assistive Access

Customize your app for Assistive Access

元の動画を見る

ハイライト

Assistive Access は、Apple が iOS/iPadOS 17 で認知障害のあるユーザー向けに設計したシンプルなシステム体験です。大きなコントロール、簡略化されたフロー、視覚化された情報表示が特徴となっています。これまで、最適化されていない app は縮小されたフレーム内に表示されていました(画面下部の戻るボタン用にスペースを確保するため)。iOS 26 では AssistiveAccess SwiftUI scene が導入され、このモード向けに完全にカスタマイズした UI を提供できるようになりました。


主要内容

認知障害のあるユーザーがあなたのお絵かき app を開くと、画面にはブラシ、消しゴム、Undo、ギャラリー、お気に入り、カラーパレット、不透明度スライダーが所狭しと並んでいます。選択肢が一つ増えるたびに、認知的な負担も増していきます。iOS 17 で Assistive Access が登場した後も、対応していない app はさらに小さなフレームに押し込められ、その下にグローバルな戻るボタンのスペースが確保されました。視覚的により窮屈で、体験としても悪化していたわけです。

iOS/iPadOS 26 では AssistiveAccess SwiftUI scene が導入され、このモード専用の UI を個別に提供できるようになりました。この scene が有効になると、標準の ButtonListNavigationLinknavigationTitle は自動的に Assistive Access の大きく目立つスタイルでレンダリングされ、ユーザーがシステム設定で選んだグリッドまたは行レイアウトに従って配置されます。画面下部の戻るボタンはナビゲーションスタックを戻る役割を担い、追加のコードは不要です(09:00)。app 自体が認知障害のあるユーザー向けに設計されている場合(AAC 補助コミュニケーション app など)は、UISupportsFullScreenInAssistiveAccess を true に設定するだけで、フルスクリーンで元の UI を維持できます。それ以外の app には、機能を中核に絞り込んだ新しい scene を採用するアプローチが推奨されます。


詳細

Assistive Access scene の導入の第一歩は、Info.plist で UISupportsAssistiveAccess を true に設定することです。これにより app がシステム設定の Optimized Apps 一覧に表示され、縮小フレームではなくフルスクリーンで起動するようになります(04:54)。次に App 本体に AssistiveAccess scene を追加します。

// Create a scene for Assistive Access

import SwiftUI
import SwiftData

@main
struct WWDCDrawApp: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
        .modelContainer(for: [DrawingModel.self])
    }
    AssistiveAccess {
      AssistiveAccessContentView()
          .modelContainer(for: [DrawingModel.self])
    }
  }
}

ポイント:

  • WindowGroup は通常モードのエントリポイントです。AssistiveAccess { ... } は新しく追加された並列の scene で、Assistive Access が有効なときにのみ生成・アタッチされます(05:55)。
  • 両方の scene に modelContainer を付与することで、SwiftData モデルを両モードで利用できるようにしています。
  • AssistiveAccessContentView はこのモード専用に設計したルートビューで、最も中核的な 1〜2 個の機能だけを配置します。

この scene のプレビューには実機へのインストールは不要で、#Preview.assistiveAccess trait を渡すだけで済みます(06:25)。

// Display an Assistive Access preview

import SwiftUI

struct AssistiveAccessContentView: View {
  @Environment(\.modelContext) var context
  var body: some View {
    VStack {
      Image(systemName: "globe")
        .imageScale(.large)
        .foregroundStyle(.tint)
      Text("Hello, world!")
    }
    .padding()
  }
}

#Preview(traits: .assistiveAccess)
    AssistiveAccessContentView()
}

ポイント:

  • traits: .assistiveAccess を指定することで、Xcode Preview に scene が有効なときの見た目をレンダリングするよう伝えられます。Assistive Access モードに何度も出入りしてデバッグする手間が省けます。

UIKit ライフサイクルの app でも、この SwiftUI scene をホストできます。scene delegate クラスの static な rootScene プロパティで宣言します(06:35)。

// Declare a SwiftUI scene with UIKit

import UIKit
import SwiftUI

class AssistiveAccessSceneDelegate: UIHostingSceneDelegate {

  static var rootScene: some Scene {
    AssistiveAccess {
      AssistiveAccessContentView()
    }
  }

    /* ... */
}

ポイント:

  • UIHostingSceneDelegate は iOS 26 で新たに追加された scene ブリッジのプロトコルで、UIKit app から SwiftUI scene をホストできるようにします。
  • rootScene は static プロパティで、some Scene を返す必要があります。

続いて AppDelegate で、scene の role に応じてこの delegate を割り当てます(06:55)。

// Activate a SwiftUI scene with UIKit

import UIKit

@main
class AppDelegate: UIApplicationDelegate {
  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let role = connectingSceneSession.role
    let sceneConfiguration = UISceneConfiguration(name: nil, sessionRole: role)
    if role == .windowAssistiveAccessApplication {
      sceneConfiguration.delegateClass = AssistiveAccessSceneDelegate.self
    }
    return sceneConfiguration
  }
}

ポイント:

  • システムが Assistive Access から app を起動した場合、role.windowAssistiveAccessApplication になります。
  • この role の場合のみ delegateClass を差し替えるため、通常モードでは元の delegate が使われ、互いに干渉しません。

ビジュアル面では、認知障害のあるユーザーは純粋なテキストよりもアイコンの方が理解しやすい傾向にあるため、ナビゲーションタイトルにもアイコンを添えるのが望ましいです。assistiveAccessNavigationIcon(systemImage:) を使うと、scene が有効なときにナビゲーションバーへアイコンが表示されます(14:36)。

// Display an icon alongside a navigation title

import SwiftUI

struct ColorSelectionView: View {
  var body: some View {
    Group {
      List {
        ForEach(ColorMode.allCases) { color in
          NavigationLink(destination: DrawingView(color: color)) {
            ColorThumbnail(color: color)
          }
        }
      }
      .navigationTitle("Draw")
      .assistiveAccessNavigationIcon(systemImage: "hand.draw.fill")
    }
  }
}

ポイント:

  • assistiveAccessNavigationIcon モディファイアは Assistive Access scene でのみ有効に作用し、通常モードには影響しません。
  • SF Symbol 名だけでなく、カスタムの Image を渡すこともできます。
  • navigationTitle を持つすべてのページにアイコンを添えることが推奨されています。

デザイン原則として、session では具体的な指針が 5 つ示されています(09:39 以降)。中核機能を 1〜2 個に絞り込むこと、同一画面の選択肢を減らすこと、隠しジェスチャーやネストされた UI を避けること、タイマーによるインタラクション(自動的に消えたり切り替わったりするビュー)を使わないこと、ステップ式の選択フローを構築して意思決定を分割することです。スピーカーはお絵かき app を例に、「色を選ぶ」操作をキャンバス内の選択肢からキャンバスに入る前の独立したステップへ変更しています。意思決定を分離することで認知負荷が下がる、というわけです(13:01)。さらに「ストロークの取り消し」や「絵の削除」のような復元の難しい操作は取り除き、残さざるを得ない破壊的な操作には二度の確認を求めるようにしています(11:33)。


重要ポイント

  • 既存の app に AssistiveAccess scene を追加する: 取り組む価値の理由 — app 全体を直接フルスクリーン化する場合と比べて、scene 方式なら標準コントロールが Assistive Access の大きなスタイルとグリッド/行レイアウトを自動的に取得でき、ほぼゼロコストで一貫したビジュアルが得られます。始め方 — Info.plist に UISupportsAssistiveAccess を追加し、App 本体に AssistiveAccess { ... } scene を並列で宣言した上で、中核機能 1〜2 個だけを持つルートビューを書きます。

  • #Preview(traits: .assistiveAccess) でデバッグを高速化する: 取り組む価値の理由 — Xcode 上で scene 有効時の見た目を直接プレビューでき、システム設定で何度もモードを切り替える時間を削減できます。始め方 — Assistive Access 用の各ビューに #Preview(traits: .assistiveAccess) { MyView() } を追加し、通常の SwiftUI プレビューと同じ感覚で利用します。

  • 「選択肢の並列表示」を「ステップ誘導」に書き換える: 取り組む価値の理由 — 同一画面の選択肢が少ないほど意思決定は完了しやすくなります。ステップ式のフローでは各ステップが 1 つの意思決定だけを担い、認知負荷が線形に低下します。始め方 — 現在のページにある独立した意思決定(色、ブラシ、キャンバスサイズなど)を棚卸しし、それぞれを前段の独立したページに分割して 1 ページ 1 問にします。メイン機能に入る前にすべての選択を完了させましょう。

  • すべての navigationTitle にアイコンを添える: 取り組む価値の理由 — 図とテキストの 2 経路は認知障害のあるユーザーにとって理解しやすく、通常モードのビジュアルにも影響しません。始め方 — navigationTitle を持つ各ビューに .assistiveAccessNavigationIcon(systemImage: "...") を追加し、機能と強く結びつく SF Symbol を選びます。

  • app 内の破壊的操作を見直す: 取り組む価値の理由 — 認知障害のあるシナリオでは、誤削除や誤操作の代償が一段と重くなります。始め方 — app 内の不可逆な操作(削除、クリア、注文確定など)を洗い出し、Assistive Access scene では必須でないものを削除することを検討してください。残す操作には二度確認のダイアログを追加します。


関連セッション

コメント

GitHub Issues · utterances