ハイライト
アクセサリのセットアップ体験は長年の課題でした。従来のフローは Bluetooth 権限の許可、場合によってはアクセサリの Wi-Fi ホットスポットへの参加、Bluetooth ペアリング——各ステップが摩擦となります。iOS 18 の AccessorySetupKit はこれらすべてを 1 つのシステム picker 画面に集約します。
主要内容
Bluetooth アクセサリのペアリングに何ステップ必要?iOS 17 以前の答え:Bluetooth 権限を要求、システムダイアログを待つ、ユーザーが許可、デバイスをスキャン、場合によっては Wi-Fi ホットスポットに個別参加、Bluetooth ペアリングを開始——各ステップでユーザーを失う可能性があります。Apple の調査でも、アクセサリ初回セットアップ時の摩擦がユーザー離脱の最大原因です。
iOS 18 の AccessorySetupKit はフローを 1 タップに圧縮。App が showPicker() を呼ぶと、システムが独立プロセスで近くのアクセサリをスキャン、提供した製品画像と名称で picker に表示し、ユーザーがタップすればペアリング完了。Bluetooth と Wi-Fi のアクセス権限はこの 1 タップで同時に付与——個別の権限ダイアログは不要。
プライバシー設計がこのフレームワークの核心。picker は独立プロセスで動作し、App は発見ルールと表示素材のみ送信。Bluetooth スキャンに直接触れません。picker では App が定義した製品名/画像とアクセサリがブロードキャストするハードウェア名の両方を表示し、ユーザーが真正性を確認できます。ペアリング後の通信は CoreBluetooth と NetworkExtension の標準 API をそのまま使用——新しい通信方式を学ぶ必要はありません。
詳細
AccessorySetupKit 利用の第一歩は Info.plist でサポート技術と発見ルールを宣言。AccessorySetupKit - Supports 配列に Bluetooth(または Wi-Fi)を追加し、Bluetooth Services にアクセサリがブロードキャストする GATT service UUID を入力(04:12)。
核心 API は ASAccessorySession。session を作成・有効化し、イベントコールバックを登録(06:02):
import AccessorySetupKit
// Create a session
var session = ASAccessorySession()
// Activate session with event handler
session.activate(on: DispatchQueue.main, eventHandler: handleSessionEvent(event:))
// Handle event
func handleSessionEvent(event: ASAccessoryEvent) {
switch event.eventType {
case .activated:
print("Session is activated and ready to use")
print(session.accessories)
default:
print("Received event type \(event.eventType)")
}
}
キーポイント:
ASAccessorySessionは picker 表示、イベント受信、アクセサリ管理の中心オブジェクトactivate(on:eventHandler:)には DispatchQueue とイベントコールバックが必要.activatedイベントは session が準備完了。既存のsession.accessoriesを読み取るか、新しいペアリングフローを開始可能
次に ASPickerDisplayItem を作成し、各アクセサリバリアントに名称、画像、発見ルールを指定(07:23):
// Create descriptor for pink dice
let pinkDescriptor = ASDiscoveryDescriptor()
pinkDescriptor.bluetoothServiceUUID = pinkUUID
// Create descriptor for blue dice
let blueDescriptor = ASDiscoveryDescriptor()
blueDescriptor.bluetoothServiceUUID = blueUUID
// Create picker display items
let pinkDisplayItem = ASPickerDisplayItem(
name: "Pink Dice",
productImage: UIImage(named: "pink")!,
descriptor: pinkDescriptor
)
let blueDisplayItem = ASPickerDisplayItem(
name: "Blue Dice",
productImage: UIImage(named: "blue")!,
descriptor: blueDescriptor
)
キーポイント:
ASDiscoveryDescriptorは発見ルールを 1 オブジェクトにまとめる。システムは記述子内の全ルールに一致するアクセサリをフィルタ- Bluetooth と Wi-Fi の両方をサポートするアクセサリは同一 descriptor に両方のルールを設定可能。1 タップで両方のアクセス権限を取得
- 異なるバリアント(色違いなど)はそれぞれ独立した descriptor と display item が必要
showPicker() でアクセサリ選択器を表示(08:10):
// Invoke accessory picker
Button {
session.showPicker(for: [pinkDisplayItem, blueDisplayItem]) { error in
if let error {
// Handle error
}
}
} label: {
Text("Add Dice")
}
キーポイント:
showPicker(for:)は display item 配列を受け取り、picker は全記述子に対応するアクセサリを同時スキャン- picker は独立プロセスで動作。App は Bluetooth スキャンに直接触れない
- コールバックの error で picker 表示不可(システム制限など)を処理
ユーザーが picker でアクセサリを選択すると、App は accessoryAdded イベントを受信(09:26):
// Handle event
func handleSessionEvent(event: ASAccessoryEvent) {
switch event.eventType {
case .accessoryAdded:
let newDice: ASAccessory = event.accessory!
case .accessoryChanged:
print("Accessory properties changed")
case .accessoryRemoved:
print("Accessory removed from system")
default:
print("Received event with type: \(event.eventType)")
}
}
キーポイント:
.accessoryAddedはASAccessoryオブジェクトを含み、ペアリング済みアクセサリの全情報を保持.accessoryChangedはアクセサリ属性変更時(設定で表示名を変更など)に発火.accessoryRemovedはユーザーまたは App がアクセサリを削除したときに発火
ペアリング完了後、CoreBluetooth でアクセサリと通信(10:22):
// Connect to accessory using CoreBluetooth
let central = CBCentralManager(delegate: self, queue: nil)
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
let peripheral = central.retrievePeripherals(withIdentifiers: [newDice.bluetoothIdentifier]).first
central.connect(peripheral)
default:
print("Received event type \(event.eventType)")
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices(pinkUUID)
}
キーポイント:
- Info.plist で AccessorySetupKit サポートを宣言しているため、Bluetooth 権限の要求は不要
CBCentralManagerの状態は App にペアリング済みアクセサリがある場合のみ.poweredOnになるASAccessoryのbluetoothIdentifierから CBPeripheral 識別子を取得し、retrievePeripherals(withIdentifiers:)で peripheral オブジェクトを取得- スキャン API も利用可能だが、App とペアリング済みのアクセサリのみ返す
既存アクセサリの移行には ASMigrationDisplayItem を使用(11:58):
// Create migration items
let pinkMigration = ASMigrationDisplayItem(name: "Pink Dice", productImage: UIImage(named: "pink")!, descriptor: pinkDescriptor)
pinkMigration.peripheralIdentifier = pinkPeripheral.identifier
// Present picker with migration items
session.showPicker(for: [pinkMigration]) { error in
if let error {
// Handle error
}
}
キーポイント:
ASMigrationDisplayItemはASPickerDisplayItemのサブクラス。既存アクセサリを AccessorySetupKit 管理へ移行peripheralIdentifierを既存 CBPeripheral の identifier に設定showPickerが移行項目のみの場合、システムは移行を通知する情報ページを表示。非移行項目と混在する場合、ユーザーが新しいアクセサリを選択・設定したときのみ移行が発生
製品画像の表示にもデザイン規範あり。picker は製品画像に 180×120 pt のコンテナを提供。画像背景は透明にし、ライト/ダークモードに対応。透明ボーダーの幅がコンテナ内のスケーリングに影響——ボーダーが広いほどアクセサリは小さく見える(12:54)。
重要ポイント
-
何をするか:Bluetooth/Wi-Fi アクセサリ App に AccessorySetupKit を導入し、従来の Bluetooth 権限要求フローを置き換え。なぜ価値があるか:ペアリングを多段階から 1 ステップに短縮し離脱率を下げ、プライバシーも向上——App はグローバル Bluetooth 権限が不要。始め方:Info.plist に
AccessorySetupKit - Supportsと発見ルールを追加。ASAccessorySessionを作成。ASPickerDisplayItemで表示項目を設定。showPicker()を呼び出し。 -
何をするか:既存アクセサリ App に移行フローを実装し、旧権限モデルから AccessorySetupKit 管理へ移行。なぜ価値があるか:Bluetooth 権限を既に許可した既存ユーザーは自動移行されない。移行しないと新しい権限管理の細かい制御を享受できない。始め方:
ASMigrationDisplayItemに既存 peripheral の identifier を渡し、showPickerで移行プロンプトを表示。 -
何をするか:picker 内の表示素材を最適化し、ライト/ダークモードで製品画像が鮮明に。なぜ価値があるか:picker の製品画像はユーザーがアクセサリを識別・検証する主要手段。画像の不鮮明さはペアリング完了率に直結。始め方:180×120 pt コンテナサイズの高解像度画像を準備。背景透明、透明ボーダー幅でスケール調整。両モードで視覚テスト。
-
何をするか:Bluetooth と Wi-Fi の両方をサポートするアクセサリは、1 つの discovery descriptor に両インターフェースルールを設定。なぜ価値があるか:1 タップで Bluetooth と Wi-Fi の両アクセス権限を取得。2 回のペアリングフローを回避。始め方:同一
ASDiscoveryDescriptorにbluetoothServiceUUIDと Wi-Fi SSID を設定。picker が両技術のペアリングを自動処理。
関連セッション
- What’s new in privacy — iOS 18 の新しい権限フローとプライバシー改善。AccessorySetupKit の権限モデル変更と密接に関連
- What’s new in location authorization — 位置情報認可の改善とベストプラクティス。iOS 18 権限フロー最適化の一部
- Meet the next generation of CarPlay architecture — CarPlay 新アーキテクチャのアクセサリ通信機構。AccessorySetupKit と同じシステムサービス領域
- Say hello to the next generation of CarPlay design system — CarPlay デザインシステム。車載アクセサリのインタラクション設計参考
コメント
GitHub Issues · utterances