WWDC Quick Look 💓 By SwiftGGTeam
Meet desktop-class iPad

Meet desktop-class iPad

元の動画を見る

ハイライト

セッションは UINavigationBar の包括的なアップグレードに焦点を当てており、インターフェイスの検出可能性、ドキュメントのサポート、検索の強化の 3 つのセクションに分かれています。


主要内容

iPadアプリの初期は、左右のバーボタン項目に主要な機能が詰め込まれていることが多かった。画面が大きくなるにつれて、このレイアウトではナビゲーション バーの中央のスペースが無駄になります。ユーザーがキーボード、トラックパッドを接続するとき、または Mac Catalyst にアプリを実行するとき、ツールバーがデスクトップ アプリのような一般的に使用される操作を直接公開することも期待します。

Apple、iOS 16を譲歩UINavigationBarデスクトップクラスの iPad に一連の機能を追加しました。まずナビゲーション バーを 3 つのスタイルに分割し、次に開発者がツールのグループをナビゲーション バーの中央領域に配置できるようにします。このようにして、描画、挿入、書式設定などの操作を他のメニューで隠す必要がなく、カスタマイズ可能なツールバー項目にすることができます。 (02:00)

2 番目の変更はドキュメント アプリに関するものです。タイトルは単なる文字列ではなくなりました。開発者はタイトルにメニューを追加して、コピー、移動、名前変更、エクスポート、印刷などのアクションを提供できます。タイトル メニューからドラッグ アンド ドロップや共有を開始することもできます。 (08:43)

3 番目の変更は検索です。 iPadOS 16 では、デフォルトで検索バーがナビゲーション バーにインライン化され、検索バーが占有する垂直方向のスペースが削減されます。UISearchController新しい検索候補機能が追加されました。ユーザーが入力すると、アプリは同時にクリック可能な候補を表示できます。 (13:12)

これらの変更には追加の利点があります。Mac を最適化する際に、UINavigationBar先頭、中央、末尾の 3 つのコンテンツ グループを自動的に翻訳します。NSToolbar、中央ツールセットのカスタム ルールを尊重します。 (07:59)

詳細

ナビゲーション バーのスタイルを選択します

UINavigationItemiOS16で追加されましたstyle財産。 sessionでは3つのスタイルを紹介します。 (02:13)

  • navigator: デフォルトのスタイル。タイトルは中央に配置され、動作は従来のナビゲーション バーと一致します。 -browser: タイトルは左側に移動され、履歴ナビゲーションと現在の場所が同様に重要なファイルや Safari などのインターフェイスに適しています。 -editor: タイトルも左揃えで、ドキュメント セレクターから入力した編集インターフェイスに適した [戻る] ボタンが表示されます。

講義では設定を与えないstyleコードのスニペット。 API関係によれば、現在のページに与えられていると理解できますnavigationItemレイアウト戦略を選択します。

// 概念例:ページ種別に応じてナビゲーションバーのスタイルを選択する
navigationItem.style = .editor

キーポイント:

  • navigationItem現在のビュー コントローラーのナビゲーション項目です。 -.editorセッション内のドキュメント編集シナリオに対応します。
  • 選ぶbrowserまたはeditor最後に、タイトルが先頭領域に移動され、ナビゲーション バーの中央により多くのスペースが空きます。

UIBarButtonItemGroup を使用して中央ツール項目を整理する

ブラウザーとエディターのスタイルにより、ナビゲーション バーの中央領域が解放されます。 iOS16の場合centerItemGroupsグループを受け取るUIBarButtonItemGroupを使用すると、ツール項目をグループで表示、移動、折りたたんだり、オーバーフローしたりすることができます。 (03:23)

最も単純な固定グループは以下から作成できます。UIBarButtonItem作成する:

let insertGroup = UIBarButtonItem(title: "Insert", image: UIImage(systemName: "photo"), primaryAction: UIAction { _ in }).creatingFixedGroup()

キーポイント:

  • UIBarButtonItemタイトルを付けた単一のボタンを定義します。Insert、SF Symbols のアイコンphoto
  • primaryActionボタンをクリックしたときに実行されるアクションです。 -creatingFixedGroup()ボタンを固定グループにラップします。
  • 固定グループは常にナビゲーション バーの最初に表示され、ユーザーはそれらを移動または削除できません。 (04:47)

グループをツールバーに残しておく必要があるが、ユーザーがその位置を変更できるようにする場合は、移動可能なグループを作成します。

// Creating the 'Draw' group

// Convenient form of
// UIBarButtonItemGroup.movableGroup(customizationIdentifier:representativeItem:items:)
let drawGroup = UIBarButtonItem(title: "Draw", )
    .creatingMovableGroup(customizationIdentifier: "Draw")

キーポイント:

  • Drawインターフェイス内のこのツール グループの名前です。 -creatingMovableGroup(customizationIdentifier:)取り外し可能なグループを作成します。
  • 移動可能なグループは削除できませんが、ユーザーが並べ替えることはできます。 -customizationIdentifierユーザーの調整した位置を追跡および保存するために使用されます。 (05:13)

複数のボタン、取り外し可能、折りたたみ可能なツール グループが必要な場合は、オプションのグループを使用します。

let shapeGroup = UIBarButtonItemGroup.optionalGroup(
    customizationIdentifier: "Shapes",
    representativeItem: UIBarButtonItem(title: "Shapes", image: UIImage(systemName: "square.on.circle")),
    items: [
        UIBarButtonItem(title: "Square", image: UIImage(systemName: "square"), primaryAction: UIAction { _ in }),
        UIBarButtonItem(title: "Circle", image: UIImage(systemName: "circle"), primaryAction: UIAction { _ in }),
        UIBarButtonItem(title: "Rectangle", image: UIImage(systemName: "rectangle"), primaryAction: UIAction { _ in }),
        UIBarButtonItem(title: "Diamond", image: UIImage(systemName: "diamond"), primaryAction: UIAction { _ in }),
    ])

キーポイント:

  • optionalGroupこのグループがユーザーによって移動または削除できることを示します。 -customizationIdentifier: "Shapes"UIKit にこのグループのカスタム状態を保存させます。 -representativeItem容量が足りない場合に表示される代表的なボタンです。 -representativeItemアクションがない場合、UIKit はメニューを合成して、ユーザーがグループ内の項目を選択できるようにします。 (05:45) -items内側の 4 つのボタンは、それぞれ正方形、円、長方形、ひし形に対応します。

最後に、これらのグループをナビゲーション項目に割り当てます。

navigationItem.customizationIdentifier = "com.jetpack.blueprints.maineditor"
navigationItem.centerItemGroups = [
    // groups in the default customization
    UIBarButtonItem(title: "Insert", image: UIImage(systemName: "photo"), primaryAction: UIAction { _ in }).creatingFixedGroup(),
    UIBarButtonItem(title: "Draw", image: UIImage(systemName: "scribble"), primaryAction: UIAction { _ in }).creatingMovableGroup(customizationIdentifier: "Draw"),
    .optionalGroup(customizationIdentifier: "Shapes",
                   representativeItem: UIBarButtonItem(title: "Shapes", image: UIImage(systemName: "square.on.circle")),
                   items: [
                    UIBarButtonItem(title: "Square", image: UIImage(systemName: "square"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Circle", image: UIImage(systemName: "circle"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Rectangle", image: UIImage(systemName: "rectangle"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Diamond", image: UIImage(systemName: "diamond"), primaryAction: UIAction { _ in }),
                   ]),
    .optionalGroup(customizationIdentifier: "Text",
                   items: [
                    UIBarButtonItem(title: "Label", image: UIImage(systemName: "character.textbox"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Text", image: UIImage(systemName: "text.bubble"), primaryAction: UIAction { _ in }),
                   ]),
    
    // additional group not in the default customization
    .optionalGroup(customizationIdentifier: "Format",
                   isInDefaultCustomization: false,
                   representativeItem: UIBarButtonItem(title: "BIU", image: UIImage(systemName: "bold.italic.underline")),
                   items:[
                    UIBarButtonItem(title: "Bold", image: UIImage(systemName: "bold"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Italic", image: UIImage(systemName: "italic"), primaryAction: UIAction { _ in }),
                    UIBarButtonItem(title: "Underline", image: UIImage(systemName: "underline"), primaryAction: UIAction { _ in }),
                   ])
]

キーポイント:

  • navigationItem.customizationIdentifierナビゲーション バーのカスタマイズを有効にし、このセットの一意の識別子を構成します。
  • UIKit は、この識別子に基づいてユーザー定義の結果を自動的に保存および復元します。 (07:02) -centerItemGroupsナビゲーションバーの中央領域にあるデフォルトのツールグループリストです。 -Insert固定グループなので常に予約制です。 -Draw保持しながら位置決めできる可動グループです。 -ShapesそしてTextオプションのグループであり、ユーザーが削除できます。 -FormatセットisInDefaultCustomization: falseは、利用可能であることを示しますが、デフォルトではナビゲーション バーに表示されません。 (07:34)

タイトルにドキュメント メニューを追加

ドキュメント アプリでは、通常、タイトルは現在のドキュメントを表します。 iOS 16では許可されていますtitleMenuProviderタイトルにメニューを追加します。有効にすると、システム提案メニューには、複製、移動、名前変更、エクスポート、印刷の 5 つのコマンドを含めることができます。特定の項目はレスポンダー チェーンに従ってフィルタリングされます。 (09:04)

navigationItem.titleMenuProvider = { suggestedActions in
    var children = suggestedActions
    children += [
        UIAction(title: "Comments", image: UIImage(systemName: "text.bubble")) { _ in }
    ]
    return UIMenu(children: children)
}

キーポイント:

  • titleMenuProvider最後に表示されるタイトル メニューを返すために使用されるクロージャです。 -suggestedActions現在の環境に基づいて UIKit によって提供される推奨メニュー項目です。 -children最初にシステムの提案を保持し、次にカスタマイズしたものを追加します。Commentsアクション。 -UIMenu(children:)システムアイテムとカスタムアイテムをタイトルメニューに結合します。

タイトルメニューからのドラッグ、ドロップ、共有をサポート

タイトル メニューにはドキュメント ヘッダーも表示され、ドラッグ アンド ドロップや共有アクセスが可能になります。キーオブジェクトはUIDocumentProperties。(10:06

let url = <#T##URL#>
let documentProperties = UIDocumentProperties(url: url)

if let itemProvider = NSItemProvider(contentsOf: url) {
    documentProperties.dragItemsProvider = { _ in
        [UIDragItem(itemProvider: itemProvider)]
    }

    documentProperties.activityViewControllerProvider = {
        UIActivityViewController(activityItems: [itemProvider], applicationActivities: nil)
    }
}

navigationItem.documentProperties = documentProperties

キーポイント:

  • UIDocumentProperties(url:)現在のドキュメントを、UIKit がメタデータとプレビューを取得できるファイル URL として記述します。 -NSItemProvider(contentsOf:)ドキュメントをドラッグ アンド ドロップの共有可能なデータ プロバイダーにラップします。 -dragItemsProvider戻るUIDragItemタイトル メニューからドキュメントをドラッグできるようにする配列。 -activityViewControllerProvider戻るUIActivityViewController、共有フォームを有効にします。 -navigationItem.documentPropertiesこのドキュメント情報はナビゲーション バーに任せてください。

インライン名前変更を実装する

UIKit には 2 つの名前変更エントリが用意されています。UINavigationItem.renameDelegateシステムのインライン UI を使用するか、実装しますUIResponder.rename(_:)独自の名前変更インターフェイスを提供します。セッションのコードはインライン スキームを示しています。 (11:57)

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.renameDelegate = self
    }
}

extension ViewController: UINavigationItemRenameDelegate {
    func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
        // Try renaming our document, the completion handler will have the updated URL or return an error.
        documentBrowserViewController.renameDocument(at: <#T##URL#>, proposedName: title, completionHandler: <#T##(URL?, Error?) -> Void#>)
    }
}

キーポイント:

  • navigationItem.renameDelegate = selfタイトルのインライン名前変更を有効にします。 -ViewController拡張機能によるコンプライアンスUINavigationItemRenameDelegate
  • navigationItem(_:didEndRenamingWith:)ユーザーの確認後に新しいタイトルを受け取ります。
  • ファイル型アプリの呼び出しが可能UIDocumentBrowserViewController名前変更 API は、新しいタイトルをドキュメント URL に適用します。

検索候補を追加する

iPadOS 16 では、デフォルトで検索バーがナビゲーション バー内に配置されます。ユーザーが検索をアクティブ化すると、アプリは入力に応じた提案を提供できます。 (13:23)

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        searchController.searchResultsUpdater = self
    }
}

extension ViewController: UISearchResultsUpdating {
    func fetchQuerySuggestions(for searchController: UISearchController) -> [(String, UIImage?)] {
        let queryText = searchController.searchBar.text
        // Here you would decide how to transform the queryText into search results. This example just returns something fixed.
        return [("Sample Suggestion", UIImage(systemName: "rectangle.and.text.magnifyingglass"))]
    }
    
    func updateSearch(_ searchController: UISearchController, query: String) {
        // This method is used to update the search UI from our query text change
        // You should also update internal state related to when the query changes, as you might for when the user changes the query by typing.
        searchController.searchBar.text = query
    }
    
    func updateSearchResults(for searchController: UISearchController) {
        let querySuggestions = self.fetchQuerySuggestions(for: searchController)
        searchController.searchSuggestions = querySuggestions.map { name, icon in
            UISearchSuggestionItem(localizedSuggestion: name, localizedDescription: nil, iconImage: icon)
        }
    }

    func updateSearchResults(for searchController: UISearchController, selecting searchSuggestion: UISearchSuggestion) {
        if let suggestion = searchSuggestion.localizedSuggestion {
            updateSearch(searchController, query: suggestion)
        }
    }
}

キーポイント:

  • searchController.searchResultsUpdater = self検索更新コールバックを現在のオブジェクトに渡します。 -fetchQuerySuggestions(for:)によるとsearchBar.text提案データを生成し、例は修正された提案を返します。 -updateSearchResults(for:)クエリが変更されたときに呼び出され、更新に使用されますsearchSuggestions
  • UISearchSuggestionItem提案のテキスト、説明、アイコンを定義します。 -updateSearchResults(for:selecting:)ユーザーが提案を選択すると呼び出されます。
  • この例では、ユーザーが手動でクエリを入力したのと同じ更新パスを使用して、選択した推奨テキストを検索ボックスに書き込みます。

重要ポイント

  • 描画アプリの共通ツールをナビゲーション バーの中央に配置: キャンバス アプリでは、挿入された画像、ブラシ、図形、テキスト、書式設定ツールを固定、移動、およびオプションのグループに分けることができます。使用centerItemGroupsデフォルトの組み合わせを提供するには、次を使用します。customizationIdentifierユーザーのツールバーの配置を保存します。

  • プロジェクト レベルの操作メニューをドキュメント タイトルに追加: メモ、ホワイトボード、ドキュメント エディターでコメントの挿入、エクスポート、印刷、名前変更が可能titleMenuProvider。エントリはタイトルに近いため、ユーザーはこれらのアクションが現在のドキュメントに影響を与えることがわかります。

  • タイトルからドキュメントをドラッグアンドドロップして共有可能: ファイル管理、デザインドラフト、PDF リーダーが使用可能UIDocumentPropertiesそしてNSItemProviderタイトル メニューから現在のドキュメントをドラッグ アウトするか、共有フォームを直接開くことができます。

  • 名前の変更をインライン操作にする: ドキュメントベースのアプリを設定できますrenameDelegateを使用すると、ユーザーはナビゲーション バーのタイトルで名前を直接変更できます。完成後はnavigationItem(_:didEndRenamingWith:)実際のドキュメントの名前変更ロジックを呼び出します。

  • 検索ボックスにクリック可能な候補を追加: データベース、お気に入り、プロジェクト管理アプリで利用可能UISearchController.searchSuggestions最近の検索、頻繁に使用されるフィルター、または一致する結果を提供して、キーボードおよびトラックパッド ユーザーがクエリをより速く完了できるようにします。

関連セッション

コメント

GitHub Issues · utterances