macOS 27とiPadOS 27でメニュー項目の画像が消える
画像だけを持ちタイトルのないメニュー項目は、macOS 27のSDKに対してリンクした場合、macOS 27では何も表示されなくなります。それ以前のSDKでは、メニュー項目のタイトルと属性付きタイトルの両方が空である場合に画像を自動的に表示する保護がApple側で用意されています。1 ところが27に対して再ビルドすると、この保護は効かなくなります。
macOS 27とiPadOS 27は、ほとんどのメニュー項目画像をデフォルトで非表示にします。そして何が消えるかは、どのSDKに対してリンクしたかで決まります。 Appleはこの結果を「macOS 26.0以前の挙動に近い」と説明していますが、要するにmacOS 26がメニュー画像を広く導入し、27がその大半を取り下げたということです。1
影響を受けるフレームワークは3つあり、それぞれ無効化の手段が異なります。preferredImageVisibility を探してたどり着いた方がSwiftUIを書いているのであれば、そのプロパティは存在しません。
要点
macOS 27は、macOS 26.0以降にリンクされたアプリに対してメニュー項目のシンボル画像をデフォルトで非表示にします。macOS 27のSDKにリンクしたアプリでは、シンボル以外の画像も失われます。12 アイコンのみのメニュー項目は27より前のSDKでは自動的に保護されますが、27で再ビルドするとその保護を失います。3 iPadOS 27では、メニュー要素に設定した画像がデフォルトで非表示になります。4 AppKitとUIKitは preferredImageVisibility を公開しており、.automatic、.visible、.hidden を指定できます。SwiftUIでは代わりに labelStyle(.titleAndIcon) を使います。5 設定・共有・プリントはシステム全体で画像を保持するため、一部のアイコンだけが見えている状態になり、自分の項目だけが壊れたと勘違いしがちです。
SDK別に見た実際の変化
AppKitの挙動は3つの別々のリリースノート項目に分かれて登場し、そのうち2つは修正として記載されています。この変更に関する解説が食い違うのはそのためです。
| リンク対象のSDK | シンボル画像 | シンボル以外の画像 | アイコンのみの項目 |
|---|---|---|---|
| macOS 26より前のSDK | 影響なし | 影響なし | 影響なし |
| macOS 26.0〜26.x | 非表示 | 表示 | 自動的に表示 |
| macOS 27のSDK | 非表示 | 非表示 | 非表示 |
基準となる項目には、NSMenu がメニュー項目のシンボル画像をすべてデフォルトで非表示にする一方、シンボル以外の画像は引き続き表示されること、そしてこの変更がmacOS 26.0以降にリンクされたアプリケーションに適用されることが記されています。1
2つ目の項目は、この非表示の範囲を広げます。「macOS 27のSDKにリンクされたアプリケーションでは、シンボル画像とシンボル以外の画像の両方が自動的に非表示になります。それ以前のSDKにリンクされたアプリケーションでは、シンボル以外の画像は引き続き自動的に表示され、既存のアプリケーション動作との互換性が保たれます。」2
3つ目の項目こそ、二度読む価値があります。3
「macOS 27より前のSDKにリンクされたアプリケーションでは、メニュー項目のタイトルと属性付きタイトルの両方が空である場合、
NSMenuはメニュー項目の画像を自動的に表示するようになりました。これは、画像がメニュー項目の内容を表す唯一の手段である場合に、既存のアプリケーション動作を維持するためのものです。macOS 27のSDKに対してリンクする場合、これらの画像は自動的に非表示になります。この設計のメニューでは、preferredImageVisibilityAPIを使用して、メニュー項目の画像が表示され続けるようにしてください。」
Appleはアイコンのみのメニュー項目のためにセーフティネットを用意し、そのうえでそのネットが新しいSDKには及ばないと明記したわけです。内容がまるごと画像であるメニュー項目は、再ビルド後に空の状態で描画されます。ソースコードは何ひとつ変わっていません。引き金は、コンパイル対象にしたSDKです。
アイコンのみのメニュー項目は、聞こえるほど特殊なものではありません。書式設定メニューのカラースウォッチ——見本そのものが選択肢です。各項目をアバターやステータス記号で識別するデバイス選択やアカウント選択。画像だけの項目を横一列に並べたリアクション欄や絵文字欄。ファイル種別アイコンを表示し、名前は別に描画する最近使った書類の一覧。いずれの場合も、画像はラベルに付随する装飾ではなく、画像こそがラベルなのです。
こうしたメニューは、クリックには反応するのに中身が空の行が並ぶだけの状態に劣化します。メニューは高さも区切り線もヒット領域も保ったままなので、自動化された目には描画の失敗として映りません。メニューに6項目あることを確認するUIテストは、変わらず通ります。スクリーンショットの差分なら捕まえられますが、項目数のアサーションでは捕まえられません。
静かであることが、この種の変更に共通する特徴です。macOS 27は確認なしにチーム間のコンテナアクセスを拒否するようにもなりました。こちらではAPIが一見正常なURLを返し、失敗は読み取りの時点まで待ち構えています。どちらの変更も、見えていた信号を沈黙に置き換え、そして本来の姿とは別のものとして表面化します。
3つのフレームワーク、3つの対処法
| フレームワーク | API | 値 |
|---|---|---|
| AppKit | NSMenuItem.preferredImageVisibility |
.automatic、.visible、.hidden |
| UIKit | UIMenuElement.preferredImageVisibility |
.automatic、.visible、.hidden |
| SwiftUI | labelStyle(.titleAndIcon) |
列挙型ではなくラベルスタイル |
AppKitとUIKitは同じ形をしています。どちらのプロパティも .automatic、.visible、.hidden を持つ ImageVisibility 列挙型を取り、どちらも NSInteger に対する RawRepresentable で、どちらも Sendable です。67
// AppKit
menuItem.preferredImageVisibility = .visible
// UIKit — also available on the updated initializers
// for UIMenu, UIAction, UICommand, and UIKeyCommand
let action = UIAction(title: "Export", image: exportImage) { _ in export() }
action.preferredImageVisibility = .visible
SwiftUIは別の道を採ります。リリースノートには「メニュー項目の Label のアイコンを常に表示すべきであることを示すには、labelStyle(_:) ビューモディファイアを .titleAndIcon スタイルとともに使用してください」とあります。5
Menu("File") {
Button {
openDocument()
} label: {
Label("Open Document", systemImage: "doc")
}
.labelStyle(.titleAndIcon)
}
もう一点、SwiftUIのデフォルトは27のSDKの挙動ではなくAppKitの基準に一致することにも注意してください。つまりシンボル画像は非表示、シンボル以外の画像は引き続き表示されます。5 上のリンク対象別の表はAppKitについて述べたものです。そのまま当てはまると考えないでください。
影響範囲は言葉の印象より狭い
各項目で書き方が違うので、プラットフォームの記述を注意深く読んでください。
UIKitの項目は、iPadOS 27.0とmacOS 27.0における「メニューバーとコンテキストメニュー」を対象としています。4 SwiftUIの項目はもっと具体的で、iPadOS 27.0とmacOS 27.0のメニューバー、「およびmacOS 27.0のコンテキストメニュー」とあります。5 iPadOSのSwiftUIコンテキストメニューには言及がありません。
UIMenuElement.preferredImageVisibility は、iOS、iPadOS、Mac Catalyst、tvOS、visionOSの27.0で利用できます。7 ただし、あるプラットフォームでAPIが提供されているからといって、そこで非表示の挙動が有効だとは限りません。Appleのリリースノートが挙動を説明しているのはiPadOSとmacOSについてです。tvOSとvisionOSは、確認済みではなく記載なしとして扱ってください。
Interface Builder側の落とし穴
コードに対応物がない項目がひとつあります。xibファイルから作成したメニュー項目について、NSMenu はメニュー項目インスペクタの「macOS 26.0 only」チェックボックスを参照します。チェックを外せば画像は表示されたまま、チェックを入れれば非表示になります。1
Interface Builder上のプロパティが、実行時の画像表示を左右するようになったわけです。メニューをxibから作っているなら、この確認作業はコード検索では済みません。誰かがインスペクタを開く必要があります。
一部のアイコンだけが生き残る理由
AppKitもUIKitも、設定・共有・プリントといったシステム全体で共通のメニュー項目については、引き続きデフォルトで画像を表示します。14 SwiftUIも同様です。5
実際に起きるのは、診断上の混乱です。アップデートしてメニューを開くと、設定や共有の横にはアイコンがあるのに、自分の項目の横にはありません。まず疑うのは、画像の読み込みに失敗した、アセットカタログが壊れた、シンボル名が間違っている、といったところでしょう。そのどれも起きていません。システムが、ごく限られた既知の項目だけを例外扱いする方針を適用しているだけです。
どのアイコンを残すか決める
5つのリリースノート項目はいずれも、どのメニュー項目に画像を表示すべきかを判断するために、更新されたHuman Interface Guidelinesを確認するよう開発者に求めています。145 その指針が何を述べているのかは確認できませんでした。HIGのメニューのページはクライアント側で描画されるためフェッチしてもほとんどテキストが返らず、APIリファレンスにあるようなJSONエンドポイントがHIGコンテンツには用意されていないのです。要約を鵜呑みにせず、ご自身で確認してください。この記事も含めての話です。
リリースノート自体に含まれる具体的な判断基準はひとつだけで、SwiftUIの項目に出てきます。メニュー項目が「アクションではなく、オブジェクトや概念を表している」場合にアイコンを表示するとよい、というものです。5
この基準は実際に使えます。開いている書類、利用可能なデバイス、保存済みのフィルタを並べるメニューはオブジェクトに名前を与えており、そこではアイコンが同一性を担います。一方、動詞が並ぶメニュー——つまり大半のメニュー——は、項目ごとにアイコンを添えても得るものは多くありません。macOS 26は画像を適用しすぎた、というのがAppleの結論であり、27はその修正だと見受けられます。
27のSDKで出荷する前にやること
まずアイコンのみのメニュー項目を洗い出す。 画像が内容のすべてである以上、最も激しく壊れるのはここです。画像があってタイトルが空の NSMenuItem、および同じ作りの UIMenu 要素には、明示的に .visible を設定する必要があります。
一律ではなく項目ごとに判断する。 どこにでも .visible を設定するのは、意図的なプラットフォーム側の変更を巻き戻してmacOS 26の状態に戻すことにほかなりません。オブジェクトかアクションかという基準のほうが、一括上書きより優れたふるいになります。
xibは別途探す。 「macOS 26.0 only」チェックボックスはプロパティ代入のようにgrepできませんが、挙動は変えてしまいます。
両方のSDK世代をサポートするなら、両方でテストする。 26に対するビルドと27に対するビルドは、同一のソースから異なる見た目を生みます。つまりスクリーンショットもUIテストも、これまでにはなかった形でSDK依存になります。
どのSDKにリンクしたかが挙動を決めるという形は、今回のリリースで繰り返し現れています。iOS 27での canOpenURL の非推奨化も同じ軸で回っており、実務上の教訓も同じです。ユーザーに何が見えるかを決めるのは、ソースではなくコンパイル時の選択なのです。
リリースノートは動くものと考える。 AppKitの3項目のうち2つは修正として記載されており、つまりベータ期間中にすでに一度挙動が変わっています。5項目すべてをBeta 4のノートに対して2026年8月1日に再検証し、ここに引用したとおりの内容であることを確認しました。何かを実行に移す前に、最新のノートで裏を取ってください。
既存コードベースの棚卸し
この変更は体系的に棚卸しできる程度に機械的であり、テスターから空のメニューを報告される前に、再ビルド前の段階で済ませておく価値があります。
深刻度の最も高いケースから始める。 タイトルが空で画像を持つ NSMenuItem は、単に地味になるのではなく、目に見えて壊れたメニューを生む唯一の失敗です。コード上では、対応するタイトルのない画像の代入を探します。
# Menu items constructed with an image and no title argument
rg 'NSMenuItem\(' --type swift -A3 | rg -B1 'image ='
rg 'setImage|\.image\s*=' --type swift | rg -i 'menu'
タイトルは3行後に設定されるかもしれず、ローカライズ済みのテーブルから読まれるかもしれないので、どちらのパターンも網羅的ではありません。結果は確定した検出ではなく、目視で確認すべき候補一覧として扱ってください。
次にxib。 「macOS 26.0 only」チェックボックスにはgrepが効きません。これはビルドから見えるどの属性でもなく、メニュー項目インスペクタの中にあるからです。メニューをInterface Builderから作っているなら、棚卸しとは各メニューを開いて各項目を確認する作業を意味します。
次にUIKitのメニュー構築部分。 UIMenu、UIAction、UICommand、UIKeyCommand はいずれも preferredImageVisibility を受け取るイニシャライザが追加されたので、後から代入するのではなく生成時に対処できます。
次にメニュー内のSwiftUI Label の使用箇所。 メニュー内の Label はソース上で他の場所の Label とまったく同じに見えるため、ここが最も見落としやすいところです。モディファイアはラベルに付け、アイコンを残したい箇所にだけ付けます。
2回ビルドして見比べる。 最も信頼できる確認方法は、そもそもコードを読みません。26のSDKと27のSDKの両方でビルドし、同じメニューを開いて、両方を撮影します。同一のソースが2つの異なるメニューを生むことこそがこの変更の核心であり、grepでは見つからないものが並べて見れば見つかります。
この最後の手順は、スクリーンショットの保護にもなります。メニューが写ったマーケティング画像、ドキュメント、App Store用の素材は、撮影した時点で最新だったSDKのもとで撮られています。出荷するビルドがもう描画しないアイコンがそこに写っているなら、それらはすでに誤りであり、ビルド工程の何ひとつとしてそれを指摘してはくれません。
押さえておきたいポイント
AppKit開発者向け:
- macOS 27のSDKにリンクすると、シンボルだけでなくシンボル以外の画像も非表示になります。SF Symbolsだけを見ていては半分を取りこぼします。
- アイコンのみのメニュー項目は27のSDKで自動保護を失い、空で描画されます。ひとつずつ preferredImageVisibility = .visible を設定してください。
- xibで定義したメニューには「macOS 26.0 only」チェックボックスがあり、コードのどこにも現れないまま表示を左右します。
UIKit開発者向け:
- preferredImageVisibility は UIMenuElement にあり、UIMenu、UIAction、UICommand、UIKeyCommand の更新されたイニシャライザにもあります。
- このプロパティはtvOSとvisionOSにも存在しますが、Appleが挙動を明記しているのはiPadOSとmacOSについてです。決めつけずに確認してください。
SwiftUI開発者向け:
- preferredImageVisibility はSwiftUI向けのAPIではありません。Label に labelStyle(.titleAndIcon) を使ってください。
- SwiftUIのデフォルトはシンボル画像を非表示にし、シンボル以外の画像は残します。これは27のSDKの挙動ではなくAppKitの基準に一致します。
よくある質問
設定と共有にアイコンが残っているのはなぜですか
システムが特定の共通メニュー項目を例外扱いしているためです。AppKit、UIKit、SwiftUIはいずれも、設定・共有・プリントといった項目についてはデフォルトで画像を表示し続けます。145 自分の項目が非表示なのにそれらのアイコンが見えるのは想定どおりの挙動であり、読み込みの失敗ではありません。
古いSDKに留まれば回避できますか
部分的には回避できますが、その線引きが重要です。macOS 26.0以降にリンクされたアプリは、すでにシンボル画像を非表示にしています。1 macOS 27のSDKより下に留まれば、シンボル以外の画像の表示は維持され、アイコンのみの項目に対する自動保護も残ります。23 ただしシンボル画像が戻るわけではありません。
画像だけでタイトルのないメニュー項目はどうなりますか
macOS 27より前のSDKでは、タイトルと属性付きタイトルの両方が空であるため NSMenu が画像を自動的に表示します。3 macOS 27のSDKではその保護は適用されず画像は非表示になるので、見える内容が何もないメニュー項目が残ります。preferredImageVisibility = .visible を設定してください。
tvOSとvisionOSでも同じですか
UIMenuElement.preferredImageVisibility はどちらでも27.0で利用できます。7 リリースノートの各項目が非表示の挙動を説明しているのは、iPadOSとmacOSについてです。あるプラットフォームにAPIが存在することは、そこで挙動が有効である証拠にはなりません。
どのアイコンを残すべきですか
リリースノートはHuman Interface Guidelinesを参照するよう促していますが、こちらは直接読むことができませんでした。SwiftUIの項目でAppleが示している判断基準は、メニュー項目が「アクションではなく、オブジェクトや概念を表している」場合にアイコンを表示する、というものです。5
出典
-
Apple、“macOS 27 Golden Gate Beta 4 Release Notes”、AppKit。Radar 170477566:
NSMenuはメニュー項目のシンボル画像をすべてデフォルトで非表示にし、シンボル以外の画像は引き続き表示される。macOS 26.0以降にリンクされたアプリケーションに適用。xibの「macOS 26.0 only」チェックボックスの挙動、preferredImageVisibilityプロパティ、設定・共有・プリントに対するデフォルトの画像表示について。機械可読版はdeveloper.apple.com/tutorials/data/documentation/macos-release-notes/macos-27-release-notes.json。2026年8月1日に再検証。 ↩↩↩↩↩↩↩↩↩ -
Apple、macOS 27 Golden Gate Beta 4 Release Notes、AppKit、Resolved Issues。Radar 179374305 (FB23070183): 「macOS 27のSDKにリンクされたアプリケーションでは、シンボル画像とシンボル以外の画像の両方が自動的に非表示になります。それ以前のSDKにリンクされたアプリケーションでは、シンボル以外の画像は引き続き自動的に表示され、既存のアプリケーション動作との互換性が保たれます。」 ↩↩↩
-
Apple、macOS 27 Golden Gate Beta 4 Release Notes、AppKit、Resolved Issues。Radar 179936632: 27より前のSDKにおける、タイトルと属性付きタイトルの両方が空のメニュー項目に対する自動的な画像表示と、macOS 27のSDKに対してリンクした場合のその挙動の削除について。 ↩↩↩↩
-
Apple、“iOS & iPadOS 27 Beta 4 Release Notes”、UIKit。Radar 170479084: iPadOS 27.0とmacOS 27.0のメニューバーおよびコンテキストメニューは、メニュー要素に設定された画像をデフォルトで表示しない。
UIMenuElementのpreferredImageVisibilityと、UIMenu、UIAction、UICommand、UIKeyCommandの更新されたイニシャライザについて。同じRadarはmacOS 27のノートにも掲載されている。 ↩↩↩↩↩ -
Apple、iOS & iPadOS 27 Beta 4 Release Notes、SwiftUI。Radar 170480710: SwiftUIはほとんどの文脈でメニュー項目のシンボル画像をデフォルトですべて非表示にし、シンボル以外の画像は引き続き表示される。
.titleAndIconを伴うlabelStyle(_:)、メニュー項目が「アクションではなく、オブジェクトや概念を表している」場合にアイコンを表示するという指針、共通のシステム項目に対するデフォルトの画像表示について。 ↩↩↩↩↩↩↩↩↩ -
Apple、“NSMenuItem.preferredImageVisibility” および “NSMenuItem.ImageVisibility”。ケースは
.automatic、.visible、.hidden。NSIntegerに対するRawRepresentable。macOS 27.0で利用可能。 ↩ -
Apple、“UIMenuElement.preferredImageVisibility” および “UIMenuElement.ImageVisibility”。ケースは
.automatic、.visible、.hidden。iOS 27.0、iPadOS 27.0、Mac Catalyst 27.0、tvOS 27.0、visionOS 27.0で利用可能。 ↩↩↩