ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
UIKitの最新情報
UIKitの最新情報や改善点をはじめ、より優れたiPadOS、iOS、Mac Catalyst Appを構築する方法をご覧ください。UIの改良、生産性に関する最新情報、APIの向上などについて解説します。また、パフォーマンス、セキュリティ、プライバシーの改善点についても解説します。
リソース
- Building a desktop-class iPad app
- centerItemGroups
- UICalendarView
- UINavigationItem.ItemStyle
- UIPageControl
関連ビデオ
WWDC22
- デスクトップクラスの編集操作を取り入れる
- デスクトップクラスのiPad Appを構築する
- デスクトップクラスのiPadの紹介
- SF Symbols 4の新機能
- SF Symbolsにおける可変カラーの採用
- Swiftの並行処理でデータ競合を排除する
- Swiftの並行処理を視覚化して最適化する
- TextKitおよびテキストビューの最新情報
- UIKitでSwiftUIを使用する
WWDC21
-
ダウンロード
iOS 16の「UIKitの新機能」へようこそ 私DimaはUIKitチームの Engineering Managerです UIKitは Appの核となる 強力なフレームワークです iOS 16の新機能をサポートするため 更新しました
今回は生産性のためのUIの改善 コントロールの強化 API の改良 そして UIKitとSwiftUIを一緒に使用する 新しい方法をお話します
UIKitでは 新しいタイトルメニューや 検索と置換 編集のインタラクションが改良された ナビゲーションバーにより 合理的で解明しやすいUIが さらに簡単に開発可能になりました ドキュメントベースのAppの強化もあります まず デスクトップクラスの ツールバー機能サポートのために アップデートしたナビゲーションバーについて
iOS 16では ドキュメントベースのAppの ニーズをサポートするため UIKitはブラウザとエディタという2つの 新しいナビゲーションスタイルを 導入しています
ブラウザスタイルはナビゲーションに履歴や フォルダ構造を使用するAppを
エディターはドキュメント編集中心のUIを 想定しています
iOS 16では様々なバーボタンがAppに追加でき サブセットはナビゲーションバーの 中央に表示されます
メニューの「ツールバーのカスタマイズ」を タップして 項目を並べ替えることができます
新しい設定はAppを再起動しても維持されます
他のAppと サイドバイサイドの モードに移行する際は サイズ変更に対応するため 入り切らない項目は自動的に オーバーフローメニューに格納されます
新しいナビゲーションスタイルに対応した タイトルメニューを追加し 複製・移動・名称変更・書き出す プリント・複製などの 標準機能をサポートしました これらは 対応するデリゲートメソッドを 実装するとメニューに表示されます タイトルメニューに カスタム項目も追加できます
さらにMac CatalystでビルドされたAppは NSToolbarとシームレスに統合することで 追加コード無しで 改良されたナビゲーションバーを活用できます
iOS 16では 様々なAppで一貫してテキストを 操作するための新しい方法を導入しています 1つ目は新しい検索と置換です 写真やカレンダーなどの データモデルオブジェクトを操作する 高度なApp内検索とは異なります 検索と置換は純粋に テキストに対してのみ動作するものです UITextViewやWKWebViewなど UIKitの組み込みビューでは フラグ設定のみで機能を有効にできます
システムにオプトインした複数のビューや ドキュメント間でもシームレスに動作します
次に 編集メニューを大幅に改修しました 入力方法によって表示が異なります タッチ操作ではよりインタラクティブな メニューに生まれ変わります
ポインターを使用する場合は フル機能のコンテキストメニューが 表示されます
これらをシームレスに提供するために UIMenuControllerと完全に置き換わる UIEditMenuInteractionを導入しました
テキストビューのメニューに アクションを挿入する
新しいAPIも用意しています 詳しくはこちらのセッションをどうぞ デスクトップクラスの編集操作を取り入れる
ひとつだけ ビジュアルUIの アップデートを紹介します iOS 16では スライドオーバーモードでのサイドバーは 追加のコードなしで 自動的に鮮やかになります UIKitが一連のプライベートビューを 管理するのです
カスタマイズ可能なナビゲーションバーや 検索と置換編集インタラクション そして強力なタイトルメニューなどは UIKitの新しい生産性向上機能です これは序章に過ぎません 詳しくは「デスクトップクラスiPadの紹介」や iOS 16のUIKit機能でサンプルAppを改良する 「デスクトップクラスのiPad Appを構築する」 をご覧ください
では 今回追加した2つの新しいコントロールと UIPageControlの機能強化の紹介に移ります
UIDatePickerの埋め込み型のカレンダーが UICalendarViewという形でスタンドアロンの フル機能コンポーネントとして利用できます UICalendarViewは複数の日付選択だけでなく 単一の日付を選択するなど さまざまな選択動作をサポートします また 選択可能な日付の範囲に加えて 個々の日付を選択から外すこともできます
デコレーションで注釈を入れることも可能です
UICalendarViewがUIDatePickerと 大きく違う点は日付をNSDateではなく NSDateComponentsで表示している点です NSDateが時点の表現であるのに対し NSDateコンポーネントは より優れた正しい日付の表示となります
NSDateComponentsは多くの柔軟性を備えるため どのNSCalendarでコンポーネントを 表現しているかを明確にする必要があります
また カレンダーの種類を正しく設定しましょう グレゴリオ暦が必要な場合は 明示的にグレゴリオ暦を指定します
先ほどのような カレンダービューを設定するには ビューの作成後デリゲートを設定します カレンダーがグレゴリオ暦の設定になるように calendarViewのcalendarプロパティを Gregorian NSCalendarに設定します
次に マルチデイト選択を設定しましょう UICalendarSelectionMultiDate オブジェクトを作成し 選択オブジェクトの 選択した日付のプロパティに データモデルから取得した既存の日付を設定し Calendarビューに表示するようにします
選択オブジェクトをカレンダービューの
選択動作に設定します カレンダーで個別の日付を 選択不可にするには カレンダー選択のデリゲート multiDateSelection:canSelectDate: メソッドを実装して 選択できる日付を制御します
選択できない日付は灰色で表示されます
個々の日付を装飾するには カレンダーデリゲートの calendarView:decorationForDateComponents メソッドを実装します
装飾がない場合は単にnilを返し デフォルトの
グレーの円については デフォルトの装飾を返します
画像の装飾の作成と 色のカスタマイズも可能です さらに必要なら customView デコレーションを使い ビュープロバイダーでビューを返します
カスタムビューの装飾は インタラクションを許可せず 利用可能なスペースにクリップされます
ページコントロールも改善しました 現在のページのカスタムインジケータに サポートを追加したので 選択されたページか否かによって 異なる画像が選択可能になりました
ページコントロールの向きと方向も 完全にカスタマイズ可能です
現在のページと違うページで インジケータが変わる 垂直ページコントロールを設定した一例です
ページコントロールの方向を上から下に設定し 好きなインジケータ画像と 現在のインジケータ画像を 設定すれば 完了です!
Appleはプライバシーと セキュリティの保護に努めています iOS 15では Appがプログラムによって ペーストボードにアクセスした場合 そのことを示すバナーが 表示されることがありました
iOS 16では システムの動作を変更しました 今後はバナーの代わりに ペーストボードの使用許可を求める アラートを表示します
ユーザーが操作する システムペーストインタフェースは ペーストボードへの暗黙のアクセスを提供し 警告を回避できます
カスタムのペーストコントロールがある場合 新しいUIPasteControlに置き換えることができ 塗りつぶされたUIButtonのように見え 動作します
ペーストボードがペースト先と互換性のある コンテンツを取得するたび有効になります
つまり これらはUIPageControlを改良して UIPasteControlセキュリティを重視した 新しい強力なUICalendarViewなのです どうぞ 試してみてください 私たちが行ったAPIの改良の説明に移ります
iOS 15では シートにディテントを追加し 柔軟でダイナミックなUIが 構築可能になりました iOS 16では カスタムデテントをサポートし 任意の大きさのシートが 作れるようになりました
利用するには「.custom」デテントを使用し シートの停止位置の高さを指定します 定数値 または最大ディテント高に対する パーセンテージを返すことができます
カスタムデテントを他のAPIから参照する場合 例えば カスタムデテントの上部を暗くするのを 無効にするために 識別子を付与することができます
カスタムブロックから返される値について セーフエリアは範囲外で フローティングシートも エッジアタッチメントも 同じ計算にするためです
システムデテントなどの詳細は UIKit動画の シートのカスタマイズと リサイズをご覧ください この動画のサンプルコードにも 新しい カスタムディテントAPIが表示されます
UIKitのSF Symbolsに 新しい機能を追加しました シンボルは モノクロ・マルチカラー 階層型・パレットの 4つのレンダリングモードに対応しています シンボルが異なるレンダリングモードの 設定でない限り UIKitはモノクロを使用します iOS 16では レンダリングモードの指定がない場合 モノクロモード以外で レンダリングするケースがあります
例えば こんなデバイスのシンボルの場合 iOS15以前ではレンダリングモードの 指定がない場合はシンボルは モノクロレンダリングを使用します
iOS 16では デフォルトは 階層型レンダリングです
シンボルのデフォルトのレンダリングモードは シンボルを表示する望ましい方法です ですからこの場合はデフォルトの階層型 レンダリングを有効にしてください 新しいUIImage.SymbolConfiguration . preferringMonochrome() APIで モノクロも要求できます
UIKitは0から1までの値に基づいて シンボルのバリエーションが表示できる 可変シンボルにも対応するようになりました Appが現在の音量レベルを シンボルで表したいときは 可変レンダリングに対応するために更新した speaker.3.wave.fillシンボルが使用できます 値0では スピーカーの波がフェードアウトし 音量が最小であることを示します 値が1まで増加するときは スピーカーの波が徐々に加わっていき 音量が大きくなることを示します
シンボルが可変レンダリングを サポートしている場合Appは0と1の間の値を 反映したシンボルのバージョンを要求できます
変数記号の使い方は簡単です UIImage の標準的なSF Symbols API で 通常の非変数バージョンの シンボルが取得できます
特定の変数値を持つシンボルの バージョン取得時は variableValueパラメータを追加します
他のレンダリングモードをミックスして さらにスタイリッシュにすることも可能です
多くのシステムシンボルが 可変レンダリングに対応し Appがカスタムシンボルを更新します
カスタム変数シンボルの作成方法は 「SF Symbolsにおける可変カラーの採用」と 「SF Symbols 4の新機能」をご覧ください
UIImageやUIColorなどの不変の型を Sendableに適合させるなど Swiftの新しいConcurrency機能で 動作するようにUIKit を近代化しました これにより コンパイラの警告なしに MainActorとカスタムアクタ間で 送信可能になりました
例えば Processorというカスタムアクターと MainActorにバインドされたImageViewerという ビューコントローラーを用意します sendImageForProcessing メソッドでは ImageViewerが Processorアクタに画像を送って加工し キラキラや虹で華やかに仕上げています UIImageは不変でProcessorは 虹やキラキラを追加するために 新しいコピーの作成が必要なので安全です
元の画像を参照しているコードには これらの変更は行われないため 共有状態は 安全でない可変 unsafe-mutedとはなりません
UIBezierPathは可変のため Sendableではないので対照的です
これまでドキュメントでしか 表現できなかったものが コンパイラでチェックできるなんて クールですよね
詳細はこの2つのセッションをご覧ください Swift並行処理を使ってデータ競合を排除する Swift並行処理を可視化して最適化する
iOS 16は外部ディスプレイを 新たに強力にサポートします 古いUIScreen APIを使用していない限り 利用のために Appの更新は必要はありません
もう Appがメイン画面に ある前提はやめましょう 必要な情報を得るには トレイルコレクションやUIScene APIなど より具体的なAPIに委ねましょう まだUIScene未使用のAppをアップグレードして マルチウィンドウ対応にしたくなりましたね
UICollectionViewとUITableViewの セルフ-サイズ セルも大幅に更新しました 今やセルもセルフ-リサイズできます! iOS 16では 可視セル内の コンテンツが変更されると それに合わせてセルが 自動的にリサイズされます
この動作はデフォルトで有効になっており UICollectionViewとUITableViewには それぞれ新しいselfSizingInvalidation プロパティがあり この新機能を制御します
以下は その仕組みです
selfSizingInvalidationが有効な場合 それを含むコレクションまたは テーブル・ビューによって サイズ変更を要求できます
UIListContentConfigurationを使って セルを構成している場合構成が変更されるたび 自動的に無効化を行います
それ以外の場合は セル または そのcontentViewに 対し invalidateIntrinsicContentSize メソッドを 呼び出してセルのサイズ変更ができます
デフォルトではアニメーション付きで performWithoutAnimationでラップすると アニメーションなしでリサイズできます UICollectionViewとUITableViewは セルからのサイズ無効化を 最適なタイミングで実行される 一回の更新に統合します
セルにAuto Layoutを使用している場合 enabledIncludingConstraintsを選択すると さらに包括的な動作が選べます セルがそのcontentView内の 自動レイアウトを検出すると invalidateIntrinsicContentSizeを呼び出し コレクションまたはテーブル・ビューが サイズ変更できるということです これによりコンテンツやレイアウト更新に応じて 自動的にサイズを調整するセルを 簡単に作成できます
UIKitはパワフルで柔軟性があります また SwiftUIを使ったUIの実装では その表現力の高さが生かされます 同じAppに両方簡単に組み込めます
iOS 16では SwiftUIで コレクションとテーブルビューの セルを構築する新しい方法があります
UIHostingConfigurationという 新しいコンテンツ構成タイプで実現します たった1行のコードでセルの中で SwiftUIを書き始めることができます 追加のビューやビューコントローラーは 必要ありません
UIHostingConfigurationを使って SwiftUIで書いた シンプルなカスタムセルを紹介します このセルを作るのは簡単です
AppにSwiftUIを統合する きっかけとなるだけでなく SwiftUIの表現力は UIKitでカスタムセルを構築するのに これ以上の方法はないことがわかります このトピックは 他にもたくさんあるので ぜひ「UIKitでSwiftUIを使用する」で 詳細をご確認ください
小さいですが 重要な変更点が複数あります ユーザーが個人を特定されるのを防ぐため UIDevice.nameはユーザーの カスタムデバイス名でなく モデル名を報告するようになりました カスタマイズした名前を使うには 資格の取得が必要です
UIDevice.orientationの設定は 非対応になりました preferredInterfaceOrientationなどの UIViewController APIで 意図するインターフェイスの向きを表現します
次にどうするか? iOS 16 SDKを使ってAppをコンパイルします テキスト編集メニューや検索・置換などの 新機能をお試しください 新しい UIKit APIを採用し強化された 新しいコントロールと 生産性機能が使用できます そして UIKitAppにSwiftUIを組み込む 新しいエキサイティングな方法を試しましょう
-
-
7:51 - Configuring a UICalendarView with multi-date selection
// Configuring a calendar view with multi-date selection let calendarView = UICalendarView() calendarView.delegate = self calendarView.calendar = Calendar(identifier: .gregorian) view.addSubview(calendarView) let multiDateSelection = UICalendarSelectionMultiDate(delegate: self) multiDateSelection.selectedDates = myDatabase.selectedDates() calendarView.selectionBehavior = multiDateSelection func multiDateSelection( _ selection: UICalendarSelectionMultiDate, canSelectDate dateComponents: DateComponents ) -> Bool { return myDatabase.hasAvailabilities(for: dateComponents) }
-
9:07 - Configure UICalendarView decorations.
// Configuring Decorations func calendarView( _ calendarView: UICalendarView, decorationFor dateComponents: DateComponents ) -> UICalendarView.Decoration? { switch myDatabase.eventType(on: dateComponents) { case .none: return nil case .busy: return .default() case .travel: return .image(airplaneImage, color: .systemOrange) case .party: return .customView { MyPartyEmojiLabel() } } }
-
10:16 - Setting up a vertical UIPageControl with custom indicators
// Vertical page control with custom indicators pageControl.direction = .topToBottom pageControl.preferredIndicatorImage = UIImage(systemNamed: "square") pageControl.preferredCurrentIndicatorImage = UIImage(systemNamed: "square.fill")
-
12:21 - Creating a custom sheet detent
// Create a custom detent sheet.detents = [ .large(), .custom { _ in 200.0 } ]
-
12:38 - Creating a custom sheet detent using a percentage of maximum detent height
// Create a custom detent sheet.detents = [ .large(), .custom { context in 0.3 * context.maximumDetentValue } ]
-
12:42 - Assigning identifiers to custom sheet detents
// Define a custom identifier extension UISheetPresentationController.Detent.Identifier { static let small = UISheetPresentationController.Detent.Identifier("small") } // Assign identifier to custom detent sheet.detents = [ .large(), .custom (identifier: .small) { context in 0.3 * context.maximumDetentValue } ] // Disable dimming above the custom detent sheet.largestUndimmedDetentIdentifier = .small
-
22:16 - UIHostingConfiguration example
cell.contentConfiguration = UIHostingConfiguration { VStack { Image(systemName: "wand.and.stars") .font(.title) Text("Like magic!") .font(.title2).bold() } .foregroundStyle(Color.purple) }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。