ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
AppKitの新機能
Macアプリ開発に関する最新機能を確認しましょう。コントロールとメニューの改善点を紹介し、(ビューの)境界の制限を取り払うツールについて解説します。ユーザーインターフェイスにモーションを追加する方法、テキスト入力の改善点の活用法、SwiftとSwiftUIで既存のコードを統合する方法について学習します。
関連する章
- 1:00 - Controls
- 5:31 - Menus
- 9:19 - Cooperative app activation
- 11:16 - Graphics
- 18:04 - Graphics: Images
- 20:54 - Text improvements
- 23:43 - Swift and SwiftUI
リソース
関連ビデオ
WWDC23
-
ダウンロード
♪ ♪
こんにちは Aasim Kandrikarです 後ほど Raleigh Ledetも加わります 私たちはAppKitチームのエンジニアです この動画はmacOC Sonomaの “AppKitの新機能”に関するお話です 幅広いトピックをカバーします 最初にAppKit Controlsの新機能と APIの強化について 新規に実装された機能による メニューの改善 macOS上でのAppの アクティベーション方法の変更点 画像やシンボルにおける グラフィックスの改良や新機能 新しいテキスト入力体験と 英語以外の 言語におけるテキストレイアウトの改善 そしてSwiftとSwiftUIでの 作業方法の改善です
macOS Sonomaでは AppKit Controlsに 新機能が追加され APIが改良されました NSTableViewとNSOutlineViewでは 多くの機能をすぐに使え AppKitを使用したMac用Appの設計に 欠かせない要素になっています
macOS Sonomaでは 新APIがコラムメニューの カスタマイズを可能にします メニューにより テーブル内の コラムの切り替えが可能です このメニューを作成し表示するため 以前は カスタムAPIの実装が必要でした しかし今ではわずか 3行のコードで追加できます 新たなデリゲートメソッド tableView userCanChangeVisibilityOfを使い 非表示にするコラムを指定すると メニューのローカライズや 再起動時の非表示コラムの状態の復元など 残りの処理をAppKitが行います
FoundationのProgressタイプは アプリが実行する作業を表します アプリで進行中のダウンロードや 処理中の画像を 表現するために使用できます macOS Sonomaでは NSProgressIndicatorで FoundationのProgressタイプを 使用可能です 新しいobservedProgressプロパティに プログレスを割り当てると バックグラウンドのスレッドでも プログレスインジケーターが 変化に応じて自動で値を更新します
ボタンベゼルスタイルAPIが更新され まったく新しいベゼルスタイルの automaticが導入されました このベゼルスタイルは ボタンのコンテンツや ビュー階層内の位置に応じて 最も適切なスタイルに適応します 例えば ボタンがウィンドウ内にある場合 プッシュボタンのスタイルが選択されます ボタンをツールバーに配置すると ツールバースタイルが選択されます 背の高いコンテンツでは フレキシブルな プッシュボタンが選択されます 自動ベゼルスタイルは すべてのボタン イニシャライザのデフォルト値です
既存のベゼルスタイルの名称は 見た目を説明するものから 使用法を示すモダンな名前に更新されました 以前の「Recessed」ボタンは 「Accessory Bar」ボタンに変更され このベゼルスタイルはAccessory Barで 最もよく使われることを示しています ベゼルスタイルは廃止され推奨されません 明示的な利用方法で 代替ベゼルスタイルを参照することは非推奨です。 新たなSplit Viewタイプとして Inspectorsが導入されました Inspectorsは現在選択されている コンテンツのコンテクスト情報を 後端に表示する Split Viewアイテムです
サイドバーと同様 Inspectorsは フルサイズのコンテンツビューが 設定されている場合 ウィンドウの高さをフルに活用します 新しいInspectorsは macOS Big Surにバックデプロイされます アプリにInspectorを 追加する方法は簡単です まず 新しいinspectorWithViewController イニシャライザを使い 新規SplitViewItemを作成します 次に 新しいsplitViewItemを 既存のsplitViewControllerに追加します 次に ツールバーデリゲートを更新し 新しいToggle Inspector Toolbar Itemを含めます 一般的に Toggle Inspectorアイテムは ウィンドウの後端の Inspector上に配置します そのためには 新たにinspectorTrackingSeparatorと flexibleSpaceを toggleInspectorアイテムの前に追加します
NSPopoverに複数の改良が加えられました まずツールバーアイテムからポップオーバーの アンカリングが可能になりました フルサイズポップオーバー コンテンツもサポートされ ポップオーバーの領域全体を 埋めることができます ツールバーアンカリングについて説明します ポップオーバーをツールバーと 相対的に表示できます
ツールバーアイテムが オーバフローメニューにある場合 ポップオーバーはオーバーフロー シェブロンに固定された状態となります
そして ポップオーバーコンテンツを ポップオーバーシェブロンに拡大できます ヘッダービューに背景色が設定されていると ポップオーバーはこのようになります 背景色がポップオーバーシェブロンに 及んでいないことに注意してください ポップオーバーコンテンツを シェブロン領域に拡大するには hasFullSizeContentプロパティを trueに設定します ポップオーバー内に コンテンツがはみ出ないよう Safe Area rectを使用してください
次にRaleighがMenusの 変更点について説明します Raleigh:ありがとう Aasim MenusはCocoaをフル活用するよう 書き直されました これにより メモリとCPUの 使用量が大幅に削減され AppKitのカーボンフットプリントを 削減できます そして新機能も使用可能になりました
具体的に セクションヘッダー パレットメニュー 新たな選択の動作 バッジを紹介したいと思います これらの機能は 新たな可能性を開き 書くコードの量を減らすことができます
セクションヘッダーは メニューのグループを構成する際に 役立つ新しい機能で 1行のコードで作成可能です 新たなクラス関数 sectionHeader(title:)を使って作成し 他のメニュー項目と同様に追加します この例では 3つの メニューセクションを作成し 各セクションにヘッダーと 2つのアイテムを設定しました
パレットメニューは 項目が横に並んだメニューを 作成できる新しい機能です これはシンプルなカラーピッカーです
メニューのpresentationStyleを .paletteに設定することで どんなメニューも パレットメニューにできます 各メニュー項目に画像を設定します テンプレート画像については AppKitが自動で適切な 選択肢の色を追加します 代わりにoffStateImageや onStateImageを設定することも可能です onStateImageは 選択を示すために使用されます
選択モードには いくつかの種類があります .selectAnyは個々のメニュー項目の 状態を切り替えますが グループ内の他の項目の状態は変化しません .selectOneは選択項目の状態をオンにして グループ内の他の項目の状態をオフにします また selectedItemsによって オンの状態の項目を取得または設定できます selectionModeとselectedItemsは 同じターゲットとアクションのペアを持つ メニュー項目を論理的なグループに 整理することで機能します パレットメニュー項目を手動で作成する際に 各項目に同じターゲット/アクションの ペアを設定してselectionModeと selectedItemsの動作を利用しましょう このテクニックは パレットメニューに 限ったものではありません 通常のメニューで同じ ターゲット/アクションペアを持つ メニュー項目にも有効です NSMenuは 一般的な パレットメニュー作成のための 便利な関数も提供しています colors配列は パレット項目の数と その色を決定します Titlesはアクセシビリティのために 使用されるので 必ず追加しましょう オプションのtemplateパラメータは 着色する雛形のイメージを指定します ここでは 旗のシンボル画像が使用されています
テンプレートを指定しない場合 AppKitのデフォルトは 塗りつぶした円です また オプションで クロージャパラメータがあります このクロージャは ユーザーがパレット内の メニュー項目を切り替えるたびに 呼び出されます メニューはクロージャに渡されます そこから selectedItemsプロパティで オン状態になっている メニュー項目の配列を取得できます
メニュー項目に様々な方法で バッジをつけることができます シンプルな文字列を使ったり カウントすることもできます
また 3つの特別なカウントバッジ 新着 アラートそしてアップデートもあります これらのバッジを使うことにより AppKitは適切なテキストを自動で追加します さらに AppKitはテキストを ローカライズ化します。 ここでは日本語を例にしています ただし メニュー項目自体や 一般的な 文字列のバッジのバリエーションは 自身でローカライズする必要があります
ここまで パフォーマンスの改善点や バッジ パレット セクションヘッダーなど 新しくなったメニューを解説しました
macOS SonomaではCooperative App Activationが導入されました Cooperative App Activationにより 予期しないアプリの切り替えを削減できます 例えば タイピング中にアプリが 切り替わることが無くなります
Cooperative App Activationには 2つの部分があります activateはコマンドではなく リクエストになりました システムは ユーザーが何をしているか コンテキストを広く考慮し Activateリクエストが 適切かどうかを判断します 新しいyield APIはアプリの未来の Activationリクエストの コンテキストに影響を与えることができます
activateがリクエストになったことで ignoringOtherAppsパラメータと オプションは無視されるようになりました そのため macOS Sonomaでは activate(ignoringOtherApps:)関数と activateIgnoringOtherAppsオプションは 共に非推奨になりました NSApplicationと NSRunningApplicationの 新しいactivate APIと置き換えてください
アクティブなアプリだけがactivateの コンテキストに影響を与えることができます これは 対象のアプリが アクティブになる前に 対象のアプリに 明確にyieldを渡すことで行います そして 対象のアプリが Activationをリクエストすると システムが判断を下す際の コンテキストとしてyieldを使用します 要求が受け入れられると Activateなアプリは非アクティブになり 対象のアプリがアクティブ化します それ以外の場合 アクティブなアプリは アクティブのままです NSWorkspaceは URLやアプリを開く際に 自動でこれを処理します
手動で別のアプリをアクティブ化するには 対象のアプリの NSRunningApplicationかバンドル識別子に yieldActivationを渡します
対象のアプリがアクティブ化を要求したり 代理でアクティブ化を行う場合 システムはyieldコンテキストを使用します 以上が新しいCooperative App Activationの仕組みとなります macOS Sonomaではさらに グラフィックスと描画に 大きな変更が加えられ 新規APIを追加しました 今後はNSBezierPathsからCGPathsを 作成したり その逆も可能になります init(cgPath:)イニシャライザとcgPath プロパティがNSBezierPathに追加されます cgPathで初期化 設定 取得すると 常にパスのコピーが返されます NSBezierPathの 更なる変化はオリジナルの CGPathやそのコピーには反映されません トールフリーブリッジはされません この追加によりCAShapeLayerの パスプロパティのような CGPath APIでNSBezierPathを使うことが コード1行で可能になりました 今後はmacOSでCADisplayLink オブジェクトを作成できます これはiOSでおなじみの CADisplayLinkと同じです CADisplayLinkとは アプリの描画をディスプレイの リフレッシュレートに同期させる タイマーアプリです 直接初期化されたディスプレイリンク オブジェクトはメインディスプレイと 同期されますが macOSは シングルディスプレイに限定されていません そのため macOSではNSView NSWindowまたはNSScreenの 新しいdisplayLink(target:selector:) 関数で ディスプレイオブジェクトリンクを 直接取得できます 最も良い方法は最も具体的な 適用要素(通常はビュー)から 直接CADisplayLinkオブジェクトを 取得することです これは ビューやウィンドウから 作成することで CADisplayLinkは デスクトップ上を移動する際に ウィンドウが表示されている ディスプレイまたはビューを自動で追跡し ディスプレイ上に無い場合は それ自体が中断されることもあるからです
このビューサブクラスでは startAnimatingが呼び出されると 2行のコードで DisplayLinkオブジェクトを作成し stepAnimation関数をコールして ビューが表示されている ディスプレイと同期します そして共通モードのメイン実行ループに displayLinkを追加しています
アニメーションが完了すると invalidateをコールして ディスプレイリンクを停止し 登録された すべての実行ループモードから削除します
NSColorには 背景の図形を塗りつぶすための システムカラーを5色追加しました これらの色は 様々な大きさの図形に対して さまざまなレベルの強調色を提供します スライダートラックや プログレスバーの背景のような 小さな図形にはsystemFillや secondarySystemFillのような 目立ちやすい 高いレベルの 強調色を使用します グループボックスやフォントの 背景のような大きな図形には quaternaryや quinarySystemFillのような より繊細な強調色が好まれます これらの塗りつぶし色は動的なものなので 「コントラストを上げる」や 「ダークモード」など さまざまな外観に自動的に対応します カスタムUIエレメントを構築する際 これらの新しい塗りつぶし色は システムデザインに適合し アクセシビリティを サポートする便利な方法です
NSViewsは描画コンテンツを 境界線でクリップします そのため このFreeForm アラートウィンドウの ヒンディ語の下部のように 思い通りに表示されないことがあります
これが良く起こるのは フォントのレンダリングや 影 バッジやセール品の炎などの サブビューのアクセントなどです これを解決する方法はあります 例えばビューを組み合わせて より大きなビューに埋め込みます しかし どの手法にも欠点があります この場合 単純な横並べで 囲みビューとボタンを組み合わせると デフォルトでは テキストの位置がそろいません 今度は別の問題を解決する必要があります
もっと良い方法があります macOS Sonomaでリンクした場合 ほとんどのNSViewsは デフォルトで 境界線でクリップしなくなりました
hitTestに変更はなく ビューの ジオメトリによって判定されます もちろんhitTestを無視して 変更することもできます ビューが境界線の外側に 描画できるようになり 計算されたvisibleRectも 境界を越えて拡張できます visibleRectを見直し 必要に応じて調整してください これは描画関数の dirtyRectパラメータにも影響します 具体的に言うと dirtyRectはビューの 境界の制約を受けません AppKitはビューの境界よりも 大きなdirtyRectも 許可する権限を持っています また AppKitは描画を必要な数の矩形に 細分化する権限も持っています これが意味することは dirtyRectを使って 描画場所ではなく 描画内容を決めるべきだということです
これは 予期しない 描画結果が発生した例です ここではdirtyRectに渡された 塗りつぶしによって 背景色が上書きされ ビュー境界の外にはみ出して ウィンドウの他のUIを 覆ってしまっています ビューはdirtyRectを使って フレームを描画していません
同様に 背景の塗りつぶしは デザインが必要とする範囲を 正確に塗る必要があります
常にdirtyRectの外側に 描画する方が安全です dirtyRectで描画を 避ける部分のデータを 決定するとパフォーマンス上 有利になります この派手なスタイルで私の名前の ストロークパスを計算すると高くつきます dirtyRectがこの小さな隅であれば テキストフレームと交差しないため ビューは複雑な計算を 回避することができます それでも背景とフレームの描画は必要ですが このパスで境界全体を塗りつぶし フレーム全体を描画しても AppKitがdirtyRectで 描画をクリップするので ビューの他の 描画部分には影響しません
この新しいNSViewの .clipsToBoundsプロパティは OS X Mavericks 10.9まで さかのぼって利用可能です しかし古いOSで.clipsToBoundsを オフにするとエッジが荒れることがあります 必要に応じてテストしてください ほとんどのビューはクリッピングオンと オフの両方で問題なく動作します コンテナビューの中には独自に 明示的な決定を行うものがあります NSClipViewはその名の通り そのように動作します ビューのデフォルトの クリッピング動作に満足できず 意図的な変更を必要とするときが あるかもしれません どのビューが明示的な clipsToBounds値を必要とするかは ケースバイケースで検討してください 正しい選択肢は ご自身の アプリのビジョンを実現できるものです では Aasimが画像についてお話します Aasim:ありがとう Raleigh シンボルはアプリを デザインするうえで不可欠です macOS Sonomaでは シンボルに シンボルエフェクトという 新しい機能が追加されました シンボルエフェクトを使うと バウンス 置きかえトランジション パルスアニメーションなどの エフェクトをシンボルに付けることができます
シンボルエフェクトは アプリ内で発生した アクションや状態の変化を 強調するのに最適な方法です シンボルエフェクトは簡単に追加できます まずimageViewのimageプロパティを シンボル画像に設定します そしてエフェクトが欲しい時に イメージビューで addSymbolEffectを呼び出します これはNSImageViewがシンボル画像を 使用しているときのみ機能します
シンボルエフェクトの使い方については “Animate symbols in your app” 動画をご覧ください macOS Venturaでは SF Symbolsがユーザーの 現在のロケールに 自動的に対応する サポートを導入しました macOS Sonomaでは アセットカタログの画像やシンボルも 同じ機能を使えます macOS VenturaのSF Symbolsと同様 デフォルトでシステムロケールに従います 固定ロケールの画像を取得するには 画像ロケールメソッドを使用します 次にハイダイナミックレンジコンテンツ HDRについてお話します HDRコンテンツは 標準コンテンツを はるかに上回る光量を表現できます macOSは複数のリリースで 拡張ダイナミックレンジをサポートしており Macbook ProのLiquid Retina XDRや Pro Display XDRなどの ディスプレイをフルに活用できます macOS SonomaではNSImageViewが HDRコンテンツを サポートするようになり アプリでHDRコンテンツを これまで以上に簡単に 表示できるようになりました HDRコンテンツを含む画像は 拡張ダイナミックレンジ対応の ハードウェアでは HDRで表示されるようになりました HDRコンテンツを 標準ダイナミックレンジで表示するには preferredImageDynamicRange プロパティを使用してください
このAPIの使用に関する詳細は “Support HDR images in your apps” 動画をご覧ください Xcode 15から アセットカタログの画像と色は NSImageとNSColorの静的プロパティとして 自動的にコードに反映されます これにより 文字列で初期化する代わりに 簡潔なドット記法で画像にアクセスできます 画像は非オプショナルなので 強制アンラップや ガードチェックも削除できます アセットカタログを変更して 画像を削除したり 名前を変更すると コンパイラがコードの不一致を 検出してアプリのビルド時に エラーを出すため 後で実行時に確認するのではなく すぐに修正が可能になります macOS Sonomaでは タイピング体験の大幅な変更と 英語以外の言語の テキストレイアウトが改善されました
現在のアクセントカラーに対応し テキストを記述する際に 光る残像が残る 新しい挿入インジケータが導入されました
次に 挿入インジケータの下に 入力モード 音声入力やCaps Lockの 状態を示す カーソルアクセサリが追加されました このアクセサリは 現在の挿入位置をフォローし 可視ビューの範囲外にある場合は ドキュメントの下部に固定されます
AppKitの標準的なテキストビューを使用する アプリには自動で追加されます カスタムテキストビューを使用する場合にも 適応できる新しいAPIを用意しました カスタムのテキスト 挿入インジケータの描画を NSTextInsertionIndicatorビューに 置き換えることができます このビューをカスタムテキストビューの サブビューとして追加すると OS内で使用できる新しい 挿入インジケータが追加されます なお 挿入インジケータのフレームの更新や 表示されているかについては ご自身で確認が必要です ご使用のテキストビューが ファーストレスポンダを離れ インジケータを非表示にする場合は displayModeプロパティをhiddenにします macOS Sonomaでは 英語以外の言語の テキストレイアウトに改良が加えられました 主なハイライトは テキストのコンテキストによって 改行のルールが異なる言語があるため 折り返しやハイフネーションを 変更したことです 例えば 韓国語の伝統的な組版では 本文は単語の途中で 改行されることがありますが タイトルテキストは 単語の区切りで改行されます 韓国語ではタイトルが 単語の途中で改行されると違和感が生じます このマップのシートでは 韓国語の「時間」という単語が 2行に改行されています macOS Sonomaでは 使用するテキストスタイルの フォントによって異なる改行が 行われるようになりました 韓国語の場合 タイトルと 見出しのテキストスタイルは このシートのように 単語の途中で改行されません 一方 本文のテキストスタイルは 適切な場合 単語の途中で改行されます 別の例を挙げます 狭いレイアウトでは ドイツ語の単語が 行幅全体よりも長くなることがあり 個々の文字が 次の行に あふれてしまうことがあります この折り返しは理想的ではありません バランスを欠き 形態素と呼ばれる 単語の構成要素が 行をまたいで分割されています macOS Sonomaでは ハイフネーションが無効な タイトルテキストフィールドがある場合 macOSは 文字折り返しではなく形態素に沿った ハイフネーションを自動で行います その結果 レイアウトのバランスが改善し 読みやすくなりました この機会に みなさんのアプリでも このテキストスタイルを採用してみましょう macOS Sonomaでは AppKitがアップデートされ Swift concurrencyやtransferableなどの Swift-firstの機能をより簡単に 採用可能になりました また SwiftUIもアップデートされ AppKitアプリの様々な場所で SwiftUIビューと変数が 使用可能になりました
AppKitクラスの大部分は メインスレッドに制限されています Swift concurrencyでは これらのクラスは適切な コンパイルエラーを発生する Main actorとしてマークされています しかしNSColorやNSShadowなどの AppKitの特定のクラスは メインスレッドの外で 安全にアクセスできます macOS Sonomaでは これらのクラスは Sendableプロトコルに準拠しており アクター境界を越えて自由に 転送できることを示しています
Transferableはオブジェクトがシリアライズ およびデシリアライズされる方法を 記述するためのSwiftプロトコルです これによりSwiftUIの ドラッグアンドドロップや 共有機能が利用可能になります macOS Sonomaでは NSImage NSColorとNSSoundが Transferableプロトコルに準拠しています これによりAppKitアプリが ドラッグアンドドロップや 共有のような機能を簡単に 採用できるようになります
macOS Ventura 13.3では NSViewControllerの新しい プロパティラッパー ViewLoadingが導入されました loadViewで初期化されるプロパティに ViewLoadingを使用します これらのプロパティが 以前はオプションだった場合 オプションとそれに関連する チェックを削除できます ビューコントローラは loadViewIfNeededを呼び出すことで プロパティが初期化されたことを確認します 同様のプロパティラッパーである WindowLoadingは NSWindowControllerのプロパティでも 利用可能です Xcode 15では AppKitビューとビューコントローラを 表示するために Previewが使用可能になりました 新しいPreviewマクロを使用して 名前を与えると ビューまたはビューコントローラを返します Previewはコードに変更を加えても 最新状態に保たれます 詳しくは“Build programmatic UI with Xcode Previews”動画をご覧ください
NSHostingViewとNSHostingControllerは AppKitアプリにSwiftUIを段階的に 導入できる素晴らしい方法です macOS Sonomaではより多くの場所で SwiftUIの採用を可能にする 機能が複数導入されました ツールバーやナビゲーション タイトルのようなSwiftUI変数が NSWindowsで動作するようになりました hostingViewがウィンドウの contentViewである場合 SwiftUIはNSWindowに自動的に利用可能な すべてのシーン変数を 橋渡しするようになりました さらに管理したい場合は NSHostingViewとNSHostingControllerに 新しいプロパティの sceneBridgingOptionsがあります これを使用するとSwiftUIビューから NSWindowに橋渡しするプロパティを 明示的に指定することができます
macOS SonomaのAppKitの 新機能の一部を紹介しました 次のステップです まずmacOS Sonoma SDKを使って アプリをコンパイルし クリッピングとアクティブ化の変更が 不必要な副作用を 生じないよう確認しましょう 次に新しいinspectorやテーブルコラムの カスタマイズAPIなど コントロールAPIを試しましょう アプリのデザインをアップデートして macOS Sonomaの シンボルエフェクトを活用しましょう 最後に Transferableや NSHostingViewの改善など Swiftにフォーカスした 新しいAppKitの追加機能を使って アプリのより多くの場所で SwiftUIを採用しましょう
ご視聴ありがとうございました macOS Sonomaの新機能の 数々をお楽しみください ♪ ♪
-
-
1:36 - Configure NSTableView column customization menu
func tableView(_ tableView: NSTableView, userCanChangeVisibilityOf column: NSTableColumn) -> Bool { return column.identifier != "Name" }
-
1:53 - Configuring NSProgressIndicator to sync with Progress
func fetchData() { let url = URL(string: "https://developer.apple.com/wwdc23/")! let task = URLSession.shared.dataTask(with: .init(url: url)) progressIndicator.observedProgress = task.progress task.resume() }
-
3:48 - Adding an inspector to your app
let inspectorItem = NSSplitViewItem(inspectorWithViewController: inspectorViewController) splitViewController.addSplitViewItem(inspectorItem) func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { [.toggleSidebar, .sidebarTrackingSeparator, .flexibleSpace, .addPlant, .inspectorTrackingSeparator, .flexibleSpace, .toggleInspector] }
-
4:38 - Show a NSPopover relative to a NSToolbarItem
func toolbarAction(_ toolbarItem: NSToolbarItem) { let popover = NSPopover() popover.contentViewController = PopoverViewController() popover.show(relativeTo: toolbarItem) }
-
18:30 - Adding symbol effects to a image view
wifiImageView.image = NSImage(systemSymbolName: "wifi", accessibilityDescription: "wifi icon") wifiImageView.addSymbolEffect(.variableColor.iterative, options: .repeating)
-
24:56 - Using @ViewLoading to remove optionality on properties
class ViewController: NSViewController { @ViewLoading var datePicker: NSDatePicker var date = Date() { didSet { datePicker.dateValue = date } } override func loadView() { super.loadView() datePicker = NSDatePicker() datePicker.dateValue = date view.addSubview(datePicker) } }
-
25:26 - Preview NSView and NSViewController using the Preview macro
#Preview("Tree Species") { let treeCellView = TreeCellView() treeCellView.species = .spruce return treeCellView }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。