ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
UIKitの新機能
UIKitの最新のアップデート内容と改良点を紹介して、より優れたiPadOS App、iOS App、Mac Catalyst Appを開発する方法について解説します。UIの改良点、生産性向上のためのアップデート内容、APIの拡張点を紹介し、パフォーマンスの向上、セキュリティとプライバシーの機能を検証します。
リソース
関連ビデオ
WWDC21
-
ダウンロード
iOS 15 の 「UIKitの新機能」へようこそ! 私の名前は マイケルです 後半は 同僚のジェイミーが ご説明します
iOS 15 には新しい 技術や機能が搭載しています 新しい機能を導入するために 素晴らしい方法で アップデートしました
ジェイミーと私は "生産性の向上" "UI の改良点" "API の強化" "パフォーマンスの向上" "セキュリティーとプライバシー" を説明します
iPadOS では 生産性の向上が重要であり 今年も例外ではありません "iPad マルチタスキング" "ナビゲーション" "ショートカット" "iPadポインタ"などの アップデートを行いました まずはマルチタスクに関する アップデートを 短いデモで見てみましょう メールでは新しいセンターシーン マルチタスク機能を採用し これまで以上に 簡単に1つのメッセージに 集中できるようにしました
メッセージを長押しすると メニューが表示され "新しいウインドウで開く" を選択 メッセージの画面中央に UI ウインドウシーンが 表示されます 手元の作業に 集中するには 良い方法です センターシーンウインドウは ドラッグアンドドロップで スプリットビューに移動 できますし ウインドウの上部にある マルチタスクメニューで スプリットビューを 選択することもできます
また マルチタスクメニューを 下にスワイプして 新しいウインドウシェルフに シーンをドッキングできます
この機能をAppに 追加するにはー 新規ウインドウシーンの 起動を作成するだけです このアクションは Appで処理可能なー NSUserActivityで作成された 起動設定を返す クロジャーを取ります それをコンテキストメニューに 追加して準備完了です
iPadOS 13.4 では マジックキーボードと ポインタを導入しました iPadOS 15 では バンド選択を追加して ポインタのサポートを 改善しました 新しい APIを 提供するだけでなく 複数選択をサポートする UICollection View では デフォルトで バンド選択を 有効にしています またポインタのアクセサリが 追加されました 任意のポインタスタイルに 二次的な形状を組合せ 追加のコンテキストを伝えて 機能を示唆できます 一度に複数の アクセサリを表示し ポインタの周囲に 配置することができます アクセサリは ポインタと同じ 流動的な性質を持ち システムが異なる アクセサリの形状や位置を シームレスに アニメーションさせます
iPadOS 15では キーボード ショートカットメニューの デザインを一新しました 分類されたショートカットと 内蔵の検索機能により 探しているショートカットを 見つけるのが 簡単になりました また新しいキーボード ショートカットメニューは iPad版とMac Catalyst版の 互換性が良くなりました
これらの新機能を 最大限に活用するには UIMenuBuilderを 採用する必要があります UIApplicationDelegateに buildMenuWithBuilder を実装します コマンドをViewやFileなど あらかじめ定義された カテゴリに割り当てるか 独自のカスタムカテゴリを 作成します カテゴリを使うにはUIResponderの keyCommandsプロパティが Appで使われているか 確認する必要があります このプロパティに割り当てられた 全てのコマンドを buildMenuWithBuilderに 移動させます "マルチタスキング" "iPad ポインタ" "キーボードショートカット メニュー"について iPad Appの レベルを上げるための 素晴らしいビデオを 用意しています iPadOS 15 では フォーカスベースの キーボードナビゲーションの サポートが強化されました tvOS フォーカスシステム に慣れている方は iPadOS で フォーカスシステムが 使えるようになったことを 喜んでいただけると思います 実際 tvOS CarPlay iPadOS およびMac Catalyst における すべてのフォーカス ナビゲーションは UIFocusSystem をベースに 構築されています iPad や Mac Catalyst の UIFocusSystemでは 矢印キーでフォーカス アイテム間を移動し タブキーでフォーカス グループ間を移動します この例では メールAppが サイドバー付きの UISplitViewControllerを 使用していますが 標準的な UIKitコンポーネント使用時ー デモのようなキーボード ナビゲーションが iPadOS 15 では デフォルトで有効になります Appでのキーボードナビゲーションの サポートについては 「iPadキーボードナビゲーション」 を 参照してください iOS生産性向上に欠かせない もう一つの機能が マルチタッチによる ドラッグ&ドロップです iOS 11 で導入された ドラッグ&ドロップは 生産性向上に欠かせない 機能です 簡単なジェスチャー1つで Appのデータをスムーズ移動でき iPadOSでは 他のAppへも移動可能です iOS 15ではUIKitによって iPhoneでも App間のドラッグ&ドロップが 可能になり 多くのインタラクション が実現しました
例えば時計バンドのアイデアを 友人と共有することがー これまで以上に 簡単になりました ジェスチャーひとつで Safari からメッセージに 写真をドラッグする ことができます
この拡張機能をサポートを するためにー ドラッグ&ドロップの API に変更はありません 技術的な詳細については 2017年に公開された 4つの素晴らしいビデオで ドラッグ&ドロップの 活用方法を説明しています 次は iOS 15 で洗練された 改良版 UI を紹介します UIToolbar と UITabBar を 改良しました この改良した外観は 下までスクロールしたときに 視覚的にコンテンツが わかりやすくなります UITabBar では SF Symbolsの サポートを強化し お気に入りのシンボルに 良い結果をもたらします UIKitはアピアランスを App内でスムーズにする為 最善を尽くしていますが いくつかの問題が 発生する可能性があります コードをチェックして バーの半透明プロパティを false に設定している 箇所がないか また標準外の edgesForExtendedLayout を持つ UIViewControllers がないか 確認する必要があります これらの条件はいずれも アピアランスで視覚的な 問題を引き起こします
新しいデフォルトの動作が Appに適していない場合は カスタムのアピアランスを 作成し それをバーの scrollEdgeAppearance プロパティに割当てください このプロパティは以前 UINavigationBar でのみ 利用可能でしたが 現在では UIToolbar と UITabBar でも利用可能です カスタムアピアランスを 設定することで 前述の 互換性のないAPIに起因する 視覚的な問題を回避できます
また新しいscrollEdgeAppearanceの 遷移実行時に UIKitが観察のための 適切なスクロールビューを 推測できない 可能性があります scrollView を 直接指定するために UIViewController に 新しい機能を追加しました ⸺ setContentScrollView for edge すべてのバーを探して 想定通りになっているか 確認してください 何か特別なことをしている場合は 必ずチェックしてください 特別な注意が必要です
iOS 15ではヘッダーの外観が 新しくなりました プレーンなリストでは セクションヘッダーが コンテンツに沿って シームレスに表示され スクロールダウンして上部に 固定されたときにのみ 背景素材が 見えるようになりました さらに 各セクションヘッダーの上に 新しいパディングが挿入され この新しいデザインで セクションを視覚的に 分離します
連絡先Appの例の様に リストコンテンツが長い時は このプレーンなスタイルを インデックスバーと組合せて 使用することで 素早くスクラビングできます
UIKit には グループ化された スタイルもあります これは多くの カスタムコンテンツや ビジュアルリッチコンテンツを 含まないUIで使用されます これは設定Appに 見られるような設定 UI や 登録フローに適しています
prominentヘッダースタイルは iPadのサイドバーリストに 使用されている 既存のサイド バーヘッダースタイルと似ています プロミネントヘッダは コンパクトサイズクラスで .sidebarリストを .insetGroupedリストに 適合させる際に使用するのに 最適な選択肢です
時計Appのアラームタブには この新しいスタイルが 採用されています 最後に視覚的に豊かな コンテンツで使用する為に ヘッダーが階層を維持して 見失わないようにする為の 特別に目立つグループ化した 新しいスタイルがあります
Watch App の Face Gallery では このスタイルが 使われています このヘッダースタイルに アクセスするには iOS 14で導入された UIListContentConfiguration APIを ご使用ください iOS 14.5 ではリスト内の セパレータを完全制御できる UIListSeparatorConfiguration が導入されました リスト全体の構成を 指定することも システム生成アピアランスを 行ごとにオーバーライドもでき セパレータを 完全に制御できます iOS 15 のシートには画面を 半分だけ覆う機能が追加され 画面上に自由に 表示できるようになりました 新しい半分の高さの機能では オプションで シートの 後ろの調光を無効にでき シートの中と後ろの両方で インタラクションができる ノンモーダルな 体験ができます iOS 15で強化された シートのすべてについては 「UIKitのシートのカスタマイズとリサイズ」 をご覧下さい
次は UIDatePicker です そう iOS 15 では 再びホイールを復活させますが 時間をタップして キーボードを使った 入力も可能になりました iPad の Magic Keyboardを 使えば 時間を直接 編集することもできます もちろん 画面をタップして ホイールを表示させる こともできます それでは同僚のジェイミーに お任せします マイクありがとう! それでは iOS 15 で強化された UIKit API について ご紹介します 最初の API の強化は 様々な面でされており UI の改良でもあります UIButton に 新しい API を追加して ボタンの見た目を柔軟に 設定できるようにしました
従来の Plain スタイル に加えて 背景がGray または Tinted そして完全に不透明な Filled が追加されました
また新しいスタイルに加えて Dynamic Typeと呼ばれる システムのテキストサイズ設定ー に応じて ボタンサイズ変更が より適切にサポートされ また初めて複数行のテキストが サポートされます これらの変更と それを可能にする 新しい UIButton Configuration APIによって より強力になっただけでなく カスタマイズ性や更新の しやすさも向上しています
iOS 14 でリリースされた ボタンへのUIMenuの追加と 合わせて UIButtonConfigurationでは 初めて UIKit で自然に ポップアップボタンや プルダウンボタンを作ることが できるようになりました
もちろんMacで UIKit を 使用していて Xcode で Optimize Interface For Mac を選択していれば これらのボタンは想定通りの 外観と動作になります
API の使いやすさの 一例をご紹介します ボタンのコンストラクション を作成します このコンストラクタでは Tintedスタイルを指定します
構成のプロパティは ボタンのカスタマイズに 使用されます コンフィギュレーションを渡し インスタンス化します ここに表示されていませんが アクションを追加してボタン をビューに追加するだけです UIButtonConfigurationには ここでは説明しきれないほど 多くの機能があるので 機能や UIButton の改良点を 説明したビデオがあります ボタンの API については 「UIKitボタンシステムについて」 をご覧ください iOS および iPadOS 上の UIContextMenuInteraction は 折畳可能なサブメニューを サポートできます このメニューの "Sort By"のように > の項目をタップすると 表示されます
このための 新しい API はありません UIMenu API はすでに サブメニューをサポートしていますが iOS 15以前では サブメニューをタップすると メニューを 完全に置き換えていました これについてはビデオ 「UIKitボタンシステムについて」で もう少し詳しく 説明しています
iOS 13 では SF Symbolsが 導入されました これはサンフランシスコの フォントの横に置いても 違和感のない数百種類の シンボルです iOS 15 では これがさらに進化しました シンボルが 追加されただけでなく 3つの新しい方法で 色を使うことができます "階層型" "パレット型" "マルチカラー型"です モノクローム型は すでにおなじみの 単色の着色可能な イメージです 階層型はランタイム指定の 単一の色をグラデーション のようにします パレット型は複数の色を 明示的に指定できます マルチカラー型は 以前 AppKit と SwiftUI でしか 利用できなかったですが 固定のマルチカラー表現が 可能になりました
カラフルなモードを 使用する為の新しい API が UIKit SwiftUI 及び AppKit で利用可能です
この API はとても簡単に 使用できます このコードでは システムの オレンジを階層的な色合いの 基準として使用する UIImageSymbolConfiguration を設定し オレンジ色に 階層的に着色された 太陽のシンボルのイメージを 作成しています
SF Symbols を日常的に 使用している方は スタイルバリエーションが あることをご存知でしょう 例えば 塗りつぶしたもの 円上のもの長方形上のもです
以前のリリースで 点線の 文字列を指定選択できました iOS 15 では UIImage API が用意されており タイプを事前指定する場合も 既存の画像のバリエーション を生成する場合も これらのバリエーションを 簡単に扱えます これは heart 文字列で 表されるシンボルと そのバリエーションの内2つで コード内で選択できます
「SF Symbols 3の詳細」 コレクションには SF Symbolsについての ビデオがあるのご覧ください
「UIKitとAppKitにおけるSF Symbols」に UIKit API の説明があります
UIContentSizeCategory の特徴はテキストサイズ設定を コードで表しています ーダイナミックタイプサイズ ラベルテキストフィールド テキスト イメージ ビュー SF Symbols を含む場合もあり 自動的に設定値に調整されます この特性をビュー階層に 適用する方法を制限する 新しい方法が追加されました よってサイズの上限や下限を 簡単に設定できます Appのテキストや画像が テキストサイズ設定で 美しく見えるようにする時に 大きな助けとなります Clock Appでは大きなタイムラベルの 大きさを制限しています
このAPIを使用し テキストサイズを 過度に制限しないで下さい これらの設定は非常に 重要な機能であり テキストサイズが最大設定の 人であっても すべてのAppの機能が利用可能で 読みやすいことが重要です 例えばすでにデフォルトサイズで 非常に大きい見出しの さらなる拡大を制限するために この設定を使用できます
すべてのプラットフォームで システムカラーが統一できます UIKit にとって どんな 意味があるのでしょうか いくつかの色に 微妙な変更があります 以前は他のフレームワークでしか 利用できなかった色が UIKit でいつでも 利用できます UIKit で systemMint や systemBrown を使いたくて ウズウズしていた方は 今がその時です!
新機能として UIColor. tintColor があります これは実行時に解決される色 Appや特徴的な階層の 現在の色調に基づいています 新しい UIButton.Configuration や カラフルな SF Symbol と 一緒に使うのに最適です
UIColorと共に色を混ぜたり 選んだりする為の 標準的な インターフェイスであるー UIColorPicker ViewController も強化されています iOS 14.5 では colorPickerViewController (didSelect:continue:)という 新しいコールバックが追加され 色の混合や変更 ピッキング完了時に AppのUI を更新できます TextKit 2 は iOS iPadOS tvOS macOS で利用可 新しい次世代のテキスト レイアウトシステムです テキストでやりたいことを 簡単に表現できる 強力な新システムで 高いパフォーマンスを 実現します UIKit はこれを採用し UITextField でも使われます このシステムは カンナダ語の様な 複雑な体系を持つ言語を Appの対応無しで より良いレイアウトにします
TextKit 2 で 出来る事 App使用法を知りたい方は 「TextKit 2について」 をご覧ください
UISceneSession は UI のインスタンスを表し Appスイッチャーの ウインドウに対応します インターフェースの状態は NSUserActivity で表します Appシーンが バックグラウンドに入ると この NSUserActivity を システムに提供し シーンが再設定されると NSUserActivity を使用して インターフェースの状態を 復元する必要があります iPadOS 15 では 効率化の為 新しい API があります テキスト入力ビューの 一時的な状態を取得したり 設定したりする 新しい方法があります UIScene コールバックは ストーリーボードが ロードされた後に状態を 復元する為の場所です Appの起動プロセスを拡張し ステートを返す非同期の モデルコードが実装されていれば UI がアクティブになる タイミングを遅らせます 我々は UIScene ベースの API に注力しています iPadOS 13 で UISceneが 導入される前からの 古い UIApplication ベースの ライフサイクルをお使いでしたら 今こそ UIScene に 切り替えるべきです すべての UIKit Appで使えます マルチウィンドウのサポートは 必須ではありませんが iPadやMacでは非常に重要です
UIScene の復習や 強化された状態復元 API の詳細は 「iPad Appを次のレベルに」 をご覧ください シーンといえば iOS 15 の UIKit では各シーンで やり取りされている 現在共有可能なコンテンツを Appが表現できる様にする 新しい API があります iOS と Mac の新機能である Siri の「Share This」や Mac Catalyst の NSSharingServicePickerToolbarItem で 使用されています 「ショートカット、Siri、提案のための 優れたアクションのデザイン」 「優れたMac Catalyst Appの条件」 のビデオで 詳細をご覧いただけます
最後の API の強化について UICollectionView と UITableView に戻ります iOS 14で 新しいAPIを 導入し セルの外観を 従来よりも遙に簡単で 一貫して設定できます
iOS 15 では クロージャベースの更新で セルの再構成が今までよりも 簡単になりました
セルのサブクラスを 作成してステートを使い updateConfiguration の オーバーライドは不要です セルを作成するのと 同じ場所で インラインでコードを 書くことができます セルが無効の時にテキストを グレーアウトさせています 同様のクロージャベースの 機能は UIButtonConfiguration API で利用できます
diffable データソースを 改良し コレクションビュー テーブルビューの更新を 容易にしました iOS 15 では差分を アニメーション化するのではなく スナップショット適用時に UI が更新されます アイテムを効率的に再構成 する為の新しい API があり アイテムのプロパティ変更時に 既存のセルに表示されている コンテンツを更新できます
UIKit が動作するデバイスには 複数のプロセッサコアと グラフィックスハードウェア が搭載されています 動画やスクロールは スムーズでないといけません iOS 15 ではこのような 特徴を持つAppの構築を 容易にする機能強化と 新しい API があります では UIKit に用意された ものの例を紹介します まず UICollectionView と UITableView に戻ります iOS 15 ではセルの プリフェッチに変更があり これは iOS 15 構築後 自動的に有効になります この変更によりAppは スクロールをスムーズに保ち セルを準備するための時間が 最大で2倍 ビジュアルフレーム約2枚分を 確保できます
多くのセルに画像が 表示されます メインの UI キューが大きな 画像のデコードに追われると スクロールが一瞬中断 されることがありました
Appコードで これを細かく制御できます 画像を準備するための 新しい関数が用意されており Appが画像表示 する時に画像を準備します これらの関数は非同期で 簡単に使用でき 画像をデコードしている間 UI キューで処理します
多くのAppで大きな画像を 小さなサイズで表示しています このような場合に新しい UIImage API があります 画像やディスプレイに関する システムの知識を利用して 効率的に画像のサイズ変更し メモリを節約するものです
コレクションビューと イメージの改良点の詳細 それを活用する方法や パフォーマンスの説明は 「超高速なリストとコレクションビューの構築」 をご覧ください
Swift は 非同期コードの記述を これまで以上に容易にする 新機能を導入しました 殆どのUIKit APIはメインの UIキューで呼び出す必要があります 我々はこれらのAPI を Main Actor としてマークし 初めてこれがコンパイル時に 強制されるようにしました UIImage の準備機能 のような他の分野では UIKit が新しい 非同期の Swift 言語機能を使って 簡単かつ安全に使用できる APIを調整しました 「Swiftのasync/awaitについて」 「AsyncSequenceについて」で 非同期コードを開発する 新しい方法をご確認下さい
さて 次は「セキュリティと プライバシー」についてです どのインターフェイスが 実際に操作されているかを システムが確認するための 新しい技術があります
これを UIKit にいくつかの 場所で統合しました Appに影響を与える 可能性を3点お話します
まず 位置情報ボタンです 新しいAPIが導入され 現在地のアクセスを一度だけ 許可するボタンを 埋め込むことができます このボタンは多くの 警告やプロンプトを出さずに タップされた時にのみ アクセスを許可します
柔軟性があり Appの外観 に合わせられますが 裏ではボタンが常に明確で 読みやすいようにしなければ 機能しません このボタンをどのように Appに組み込むかを 「Locationボタンについて」 のビデオでご覧下さい
iOS 14 で導入したバナーに 気付いているかもしれません これは他のAppで ペーストボードにコピーした データにアクセスするときに 表示されます
iOS 15 ではシステムの 標準的なペースト機能で 意図的に操作した後 データにアクセスした事が システムで確認できる場合は バナーを非表示にします 例えば 編集メニューの ペーストのタップや ハードウェアキーボードの Cmd-Vなどです
標準的なペーストメニュー 項目の API を追加しました これらを使用した場合 通知バナーも表示されません "ペースト" "ペーストして移動" "ペーストして検索" "ペーストしてスタイル統一" の新しい指定方法があります それぞれについて標準の UIResponderセレクタ ーUIMenuControllerや UICommandで使用 と 新しい識別子 ーUIActionで使用があります
Appがペーストボード上の 情報を求める事がありますが 全てにアクセスする 必要はありません iOS 14で ペーストボードに 数字 URL 検索用語候補が あるかチェックする為に API を導入しました 計算機や Safari で これらを使用しています
iOS 15 はこの API が 拡張され 全ての標準的な データ検出タイプを網羅しています これらはデータ自体への アクセスを 許可していないため 通知は表示されません テキストをパースせずにデータ値を 取得する API もありますが 標準的な貼り付け インターフェース使用後以外で 使用された場合 システムは ペースト通知を表示します
最後はプライバシー強化 iOS 14.5 の新機能です 位置情報 貼り付け インターフェース技術ベース UIEventAttribution は WebKit と共同開発しました WebKit の Private Click Measurement は Web-to-Web クリック計測 UIEventAttribution は PCM を UIKit に導入し App-to-Web Click Measurement を提供 広告のクリックやタップの プライバシー保護の測定です 使い方は簡単で UIEventAttributionViews で広告を覆い 広告のタップに反応して 開いたURLと一緒に UIEventAttribution オブジェクトを渡すだけです
「プライバシーを保護した 広告アトリビューションについて」 また WebKit.orgのブログ記事 「Introducing Private Click Measurement」 でも確認できます 盛りだくさんの内容でしたが すべてを網羅できていません 次は何でしょう? iOS 15 SDK でAppを コンパイルしてみてください iPhone で 新機能を試してみましょう 新しい「ボタン」「バー」 「リスト」「シンボル」など iOS 15 の新しい外観を 採用してください "マルチタスキング" "キーボード" "トラックパッドサポート"が 強化した iPad の新機能を 活用することもできます UIKit API を使って プライバシーを尊重し より速いAppを 簡単に作ることができます ありがとうございます
-
-
1:41 - Building an "Open in New Window" action
// Building an "Open in New Window" action let newSceneAction = UIWindowScene.ActivationAction({ _ in // Create the user activity that represents the new scene content let userActivity = NSUserActivity(activityType: "com.myapp.detailscene") // Return the activation configuration return UIWindowScene.ActivationConfiguration(userActivity: userActivity) })
-
3:06 - UIMenuBuilder
class AppDelegate: UIResponder, UIApplicationDelegate { override func buildMenu(with builder: UIMenuBuilder) { // Use the builder to modify the main menu... } }
-
6:26 - UIBarAppearance
let appearance = UITabBarAppearance() appearance.backgroundEffect = nil appearance.backgroundColor = .blue tabBar.scrollEdgeAppearance = appearance let scrollView = ... // Content scroll view in your app viewController.setContentScrollView(scrollView, for: .bottom)
-
11:31 - Creating a button with UIButton.Configuration
// Creating a button with UIButton.Configuration var config = UIButton.Configuration.tinted() config.title = "Add to Cart" config.image = UIImage(systemName: "cart.badge.plus") config.imagePlacement = .trailing config.buttonSize = .large config.cornerStyle = .capsule self.addToCartButton = UIButton(configuration: config)
-
13:30 - Using a hierarchical color symbol
// Using a hierarchical color symbol let configuration = UIImage.SymbolConfiguration( hierarchicalColor: UIColor.systemOrange ) let image = UIImage( systemName: "sun.max.circle.fill", withConfiguration: configuration )
-
19:30 - New UICollectionViewCell.configurationUpdateHandler closures
// New UICollectionViewCell.configurationUpdateHandler closures let cell: UICollectionViewCell = ... cell.configurationUpdateHandler = { cell, state in var content = UIListContentConfiguration.cell().updated(for: state) content.text = "Hello world!" if state.isDisabled { content.textProperties.color = .systemGray } cell.contentConfiguration = content }
-
21:01 - Image display preparation
// Image display preparation if let image = UIImage(contentsOfFile: pathToImage) { // Prepare the image for display asynchronously. Task { let preparedImage = await image.byPreparingForDisplay() imageView.image = preparedImage } }
-
21:29 - Image thumbnailing
// Image thumbnailing if let bigImage = UIImage(contentsOfFile: pathToBigImage) { // Prepare the thumbnail asynchronously. Task { let smallImage = await bigImage.byPreparingThumbnail(ofSize: smallSize) imageView.image = smallImage } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。