WWDC Quick Look 💓 By SwiftGGTeam
Take your iPad apps to the next level

Take your iPad apps to the next level

元の動画を見る

ハイライト

iPadOS 15 では、iPad アプリの生産性を向上させるための 3 つのコア機能が導入されています。Prominent Scenes によりモーダル中心のインタラクションが可能になり、UIMenuBuilder によりキーボード ショートカットに分類され検索可能なメニュー インターフェイスが可能になり、ポインター アクセサリとバンド選択によりポインター操作に複数選択機能と視覚的なプロンプト機能が追加されます。

主な内容

iPad ユーザーは、複雑なタスクを完了するためにデバイスにますます依存しています。ただし、マルチウィンドウ管理、キーボード ショートカットの検出、ポインタの操作などのデスクトップ レベルの機能は、iPad では完全ではありません。iPadOS 15 はこれら 3 つの方向から同時に動作します。

著名なシー​​ン: フォーカス モードの新しいウィンドウ

02:54

iPadOS 13ではマルチウィンドウが導入されましたが、すべてのウィンドウが横長になります。iPadOS 15 新しいprominent新しいウィンドウがモーダルに表示され、背景ウィンドウが自動的に暗く表示される表示スタイル。これは、1 つのドキュメントまたは電子メールに集中する必要があるシナリオに適しています。

使用prominentシーンは 3 つの条件を満たしている必要があります。コンテンツが独立していて完全であること、[完了] または [閉じる] ボタンがあること、特定のコンテンツ (単一のドキュメントなど) に焦点を当てていることです。システムが提供するのは、UIWindowScene.ActivationActionを使用すると、開発者はわずか数行のコードで「新しいウィンドウで開く」オプションをコンテキスト メニューに追加できます。

キーボード ショートカット メニュー: 非表示から検出可能へ

14:11

iPadOS 15では、Commandキーを長押しすると、新しいショートカットメニューが表示されます。メニューはファイル、編集、表示などのカテゴリごとに整理されており、検索をサポートしており、直接クリックしてトリガーすることもできます。これは Mac Catalyst と同じメニュー バーを共有しますUIMenuBuilder API。

主な変更点: 以前に渡されたUIResponder.keyCommandsまたはaddKeyCommand宣言されたショートカット キーは、未分類の領域に表示されます。iPadOS 15ではすべてのショートカットキーを渡す必要がありますbuildMenu(with:)メイン メニュー システムに登録して、完全な分類と検索エクスペリエンスを取得します。

ポインタの機能強化: バンドの選択とアクセサリ

26:42

iPadOS 15 は Mac からバンド選択インタラクションを借用しています。複数選択のサポートUICollectionViewオンにすると、クリックしてドラッグすると選択範囲の四角形が自動的に引き出され、枠で囲まれたセルが選択されます。Shift選択範囲を追加するキー、Commandキーを押して選択状態を切り替えます。

ポインター アクセサリーも新しい機能です。開発者は、矢印やプラス記号などの視覚的なキューをポインタに付加して、ビューをドラッグしたり、特定の操作を実行したりできることをユーザーに伝えることができます。アクセサリはポインタのスタイルとは独立しており、リフトやハイライトなどの効果と組み合わせて使用​​できます。

##詳細

「新しいウィンドウで開く」アクションを作成する

04:56

let newSceneAction = UIWindowScene.ActivationAction { _ in
    let userActivity = NSUserActivity(activityType: "com.myapp.detailscene")
    return UIWindowScene.ActivationConfiguration(userActivity: userActivity)
}

キーポイント:

  • UIWindowScene.ActivationActionはいUIActionのサブクラスは、メニュー、ボタン、ナビゲーション バーのボタンで直接使用できます。
  • クロージャリターンUIWindowScene.ActivationConfiguration、これには、NSUserActivity新しいシーンの内容を表します
  • iPad および Mac Catalyst では「新しいウィンドウで開く」を表示、iPhone では自動非表示

iPhone に代替動作を提供する必要がある場合は、次のように渡すことができます。alternateパラメータ:

let alternateAction = UIAction(title: "Show Details", image: nil) { _ in
    // iPhone 上的替代行为
}

let newSceneAction = UIWindowScene.ActivationAction(
    alternate: alternateAction
) { _ in
    let userActivity = NSUserActivity(activityType: "com.myapp.detailscene")
    return UIWindowScene.ActivationConfiguration(userActivity: userActivity)
}

コレクション ビューのジェスチャにより新しいシーンが開きます

06:58

func collectionView(_ collectionView: UICollectionView,
                    sceneActivationConfigurationForItemAt indexPath: IndexPath,
                    point: CGPoint) -> UIWindowScene.ActivationConfiguration? {
    guard let itemActivity = itemUserActivity(at: indexPath) else {
        return nil
    }
    return UIWindowScene.ActivationConfiguration(userActivity: itemActivity)
}

キーポイント:

  • 成し遂げるUICollectionViewDelegateピンチして展開するジェスチャをサポートする新しい方法
  • 戻るnilセルが新しいウィンドウで開くことをサポートしていないことを示します
  • でのみ使用できますprominentスタイルシーン表示

カスタムシーントランジションプレビュー

08:53

let itemActivity = NSUserActivity(activityType: "com.myapp.detailscene")
let configuration = UIWindowScene.ActivationConfiguration(userActivity: itemActivity)

if let cell = collectionView.cellForItem(at: indexPath) as? ThumbnailCell {
    configuration.preview = UITargetedPreview(view: cell.thumbnailView)
}

return configuration

キーポイント:

  • デフォルトの遷移はセル全体から始まり、によって設定されます。previewセルのサブビューからトランジションを開始できます
  • UITargetedPreviewトランジションアニメーションの開始点ビューを指定します
  • これにより、アニメーションがコンテンツの関係をより正確に反映できるようになります。

シーン状態の保存と復元

10:18

func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? {
    guard let viewController = self.window?.rootViewController as? EditorViewController else {
        return nil
    }

    let stateActivity = NSUserActivity(activityType: "com.myapp.editorstate")
    stateActivity.addUserInfoEntries(from: [
        "content": viewController.textField.text ?? "",
        "interactionState": viewController.textField.interactionState ?? NSNull()
    ])

    return stateActivity
}

キーポイント:

  • interactionStateこれは iPadOS 15 の新しい属性であり、カーソル位置、スクロール位置、ファーストレスポンダのステータスなどのインタラクティブな情報が含まれます。
  • 最初にコンテンツを復元する必要があります。その後、インタラクティブな状態を復元できます。
  • iPadOS 15の新機能scene(_:restoreInteractionState:)デリゲート メソッド。ストーリーボードが読み込まれた後、初めてフォアグラウンドに入る前に呼び出されます。

非同期リカバリのステータス:

func scene(_ scene: UIScene, restoreInteractionState stateRestorationActivity: NSUserActivity) {
    guard let viewController = window?.rootViewController as? EditorViewController else { return }

    scene.extendStateRestoration()

    loadContentAsync { result in
        viewController.textField.text = result.content
        scene.completeStateRestoration()
    }
}

キーポイント:

  • extendStateRestoration()リカバリ時間の延長をリクエストすると、起動イメージが表示されたままになります
  • リカバリの完了後に呼び出す必要がありますcompleteStateRestoration()そうでない場合、システムはアプリを強制的に閉じます。
  • ネットワークリクエストなど、長時間実行される可能性のあるタスクには適していません。

メインメニューをカスタマイズする

17:15

override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
    guard builder.system == .main else { return }

    let tabMenu = UIMenu(options: .displayInline, children: [
        UIKeyCommand(title: "New Tab",
                     action: #selector(newTab(_:)),
                     input: "t",
                     modifierFlags: .command),
        UIKeyCommand(title: "Close Tab",
                     action: #selector(closeTab(_:)),
                     input: "w",
                     modifierFlags: .command)
    ])
    builder.insertChild(tabMenu, atStartOfMenu: .file)

    let bookmarksMenu = UIMenu(title: "Bookmarks", children: [...])
    builder.insertSibling(bookmarksMenu, afterMenu: .view)
}

キーポイント:

  • 存在するUIApplicationDelegate中程度の書き換えbuildMenu(with:)
  • builder.system == .mainこれはメインメニューを変更する場合にのみ実行してください。
  • UIMenu.Identifierシステムメニューの識別子定数を提供します
  • 各メニュー要素には一意の識別子が必要です。ショートカット キーの組み合わせを繰り返すと挿入が失敗し、コンソール ログが出力されます。

ショートカット キーの使用可能性を動的に制御する

22:38

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    if action == #selector(closeTab(_:)) {
        return !openTabs.isEmpty
    }
    return super.canPerformAction(action, withSender: sender)
}

override func validate(_ command: UICommand) {
    if command.action == #selector(toggleBookmark(_:)) {
        command.title = currentTab.isInBookmarks
            ? "Remove from Bookmarks"
            : "Add to Bookmarks"
    } else {
        super.validate(command)
    }
}

キーポイント:

  • canPerformActionショートカットキーが実行可能かどうかを判断してリターンfalse次の場合、ショートカット キーがメニューに非表示になります。
  • validateショートカット キーがトリガーされる前に呼び出され、タイトルやアイコンなどの外観を動的に変更できます。
  • 両方のメソッドを呼び出す必要がありますsuper明らかになったケースを処理する

バンド選択 複数選択のインタラクション

28:47

let selectionInteraction = UIBandSelectionInteraction { [weak self] interaction in
    guard let self = self else { return }

    if interaction.state == .selecting {
        self.selectItemsInRect(interaction.selectionRect)
    } else if interaction.state == .ended {
        self.finalizeSelection()
    }
}

view.addInteraction(selectionInteraction)

キーポイント:

  • UIBandSelectionInteractionカスタム ビューに適しており、UICollectionView は自動的にサポートします
  • selectionRect現在の選択ボックスの長方形の領域です
  • initialModifierFlagsドラッグ開始時に押された修飾キー (Shift、Command など) を提供します。

Pointer Accessories

33:27

func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: UIPointerRegion) -> UIPointerStyle? {
    let preview = UITargetedPreview(view: self)
    let style = UIPointerStyle(effect: .lift(preview))

    if #available(iOS 15.0, *) {
        style.accessories = [
            .arrow(.left),
            .arrow(.right)
        ]
    }

    return style
}

キーポイント:

  • accessoriesiOS 15の新機能UIPointerStyle財産
  • .arrow(.left)そして.arrow(.right)これはシステム定義済みの矢印アクセサリです。
  • アクセサリの位置と角度をカスタマイズできます。UIPointerAccessory.Position(offset: 23.0, angle: .pi * 1.25)

重要ポイント

1. ドキュメント アプリに Prominent Scene サポートを追加

アプリがドキュメント、電子メール、メモなどを処理する場合は、ユーザーが個々のアイテムを新しいウィンドウで開くことができるようにします。これにより、マルチタスクの効率が直接的に向上します。

実装アイデア: コンテンツ項目ごとに作成NSUserActivity、コンテキストメニューに追加しますUIWindowScene.ActivationAction。設定activationConditionsシステムがリクエストを正しくルーティングしていることを確認します。

2. キーボード ショートカットをメイン メニュー システムに整理します。

すべての既存のコードを監査するkeyCommands属性とaddKeyCommand電話をかける、移行するbuildMenu(with:)。これにより、iPad と Mac の両方でショートカット キーに統一された検出エクスペリエンスが提供されます。

実装アイデア:機能(ファイル、編集、表示など)ごとに分類し、適切に設定するdiscoverabilityTitle、ショートカット キーの競合を処理します (たとえば、Command-I が斜体のショートカット キーと競合する場合は、代わりに Control-Command-I を使用します)。

3. カスタム ビューにバンド選択を実装する

アプリにキャンバスまたはグリッド状のレイアウトがある場合、ユーザーは複数の項目を選択する必要がある場合があります。UIBandSelectionInteractionこれを簡単にしましょう。

実装アイデア: 作成するUIBandSelectionInteraction、によるとinteraction.stateそしてselectionRect選択ステータスを更新します。組み合わせるinitialModifierFlags選択を追加する Shift と選択を切り替えるコマンドをサポートします。

4. ポインター アクセサリを使用して、ドラッグ可能なビューを表示する

ポインタがドラッグ可能なビュー上にあると、ドラッグの方向を示す矢印アクセサリが表示されます。これは、単純なポインタの形状変更よりも直感的です。

実装アイデア: でUIPointerInteractionstyleForメソッド内でビューステートに応じてバンドを返しますaccessoriesUIPointerStyle。組み合わせるlatchingAxesドラッグ時にポインタ効果がビューに追従するようにします。

5. シーン状態の回復を改善する

ユーザーは、アプリを切り替えたり、デバイスを再起動したりすると、以前の動作状態に戻ることを期待します。コンテンツの状態とインタラクション状態 (カーソル位置、スクロール位置) を保存します。

実装アイデア: でstateRestorationActivity(for:)コンテンツを保存し、interactionState。存在するscene(_:restoreInteractionState:)回復。リカバリに非同期ロードが必要な場合は、次を使用します。extendStateRestoration()そしてcompleteStateRestoration()

関連セッション

コメント

GitHub Issues · utterances