macOS 27 與 iPadOS 27 的選單項目圖片會消失
在 macOS 27 上,只要您連結的是 macOS 27 SDK,一個只有圖片、沒有標題的選單項目就會渲染成一片空白。在更早的 SDK 上,Apple 替這種情況留了後路:當選單項目的標題與屬性標題皆為空時,系統會自動顯示圖片。1但只要改用 27 重新建置,這層保護就失效了。
macOS 27 與 iPadOS 27 預設隱藏大多數選單項目圖片,而消失的究竟是哪些,取決於您連結的是哪一個 SDK。Apple 把這個結果形容為「近似於 macOS 26.0 之前的行為」,換句話說:macOS 26 大範圍地為選單加上圖片,而 27 又把大部分收了回去。1
受影響的框架有三個,每一個的解除方式都不一樣。如果您搜尋過 preferredImageVisibility 又剛好寫的是 SwiftUI,那麼這個屬性對您而言並不存在。
快速摘要
對於連結 macOS 26.0 及後續 SDK 的 App,macOS 27 預設隱藏選單項目的符號圖片;若是連結 macOS 27 SDK 的 App,連非符號圖片也一併消失。12純圖示的選單項目在 27 之前的 SDK 上受到自動保護,而在以 27 重新建置後便失去這層保護。3iPadOS 27 預設隱藏設定於選單元素上的圖片。4AppKit 與 UIKit 提供 preferredImageVisibility,值有 .automatic、.visible 與 .hidden;SwiftUI 則改用 labelStyle(.titleAndIcon)。5「設定」、「分享」與「列印」在全系統範圍內保留各自的圖片,因此您會看到部分圖示仍在,進而誤以為自己的圖片壞了。
依 SDK 區分的實際變動
AppKit 的這項行為分散在三則發行說明條目中,其中兩則被歸類為問題修正,這也是各方對這項變動的說法彼此矛盾的原因。
| 連結對象 | 符號圖片 | 非符號圖片 | 純圖示項目 |
|---|---|---|---|
| macOS 26 之前的 SDK | 不受影響 | 不受影響 | 不受影響 |
| macOS 26.0 至 26.x | 隱藏 | 顯示 | 自動顯示 |
| macOS 27 SDK | 隱藏 | 隱藏 | 隱藏 |
基準的那一則條目指出,NSMenu 預設隱藏所有選單項目的符號圖片,非符號圖片則維持可見,且此變動適用於連結 macOS 26.0 及後續 SDK 的應用程式。1
第二則條目擴大了隱藏範圍:「對於連結 macOS 27 SDK 的應用程式,符號與非符號選單項目圖片現在都會自動隱藏。對於連結較早 SDK 的應用程式,非符號圖片仍會自動維持可見,以保留既有的應用程式行為。」2
第三則條目才是值得讀兩遍的那一則:3
「對於連結 macOS 27 之前 SDK 的應用程式,當選單項目的標題與屬性標題皆為空時,
NSMenu現在會自動顯示選單項目圖片。這在圖片是選單項目內容唯一呈現方式時,保留了既有的應用程式行為。而連結 macOS 27 SDK 時,這些圖片將自動隱藏;採用此種設計的選單應改用preferredImageVisibilityAPI,以確保選單項目圖片維持可見。」
Apple 為純圖示的選單項目架了一張安全網,接著又白紙黑字寫明:這張網不延伸到新的 SDK。凡是整個內容就是一張圖片的選單項目,重新建置後就會渲染成空白。您的原始碼一個字都沒改,觸發條件是您編譯時所依據的 SDK。
純圖示選單項目其實沒有聽起來那麼罕見。格式選單裡的色票,色塊本身就是選項;以頭像或狀態圖示區分每一列的裝置或帳號選擇器;以純圖片項目橫向排成一列的表情反應與 emoji 列;顯示檔案類型圖示、檔名另行渲染的最近文件清單。在這些情況下,圖片並不是掛在標籤旁的裝飾——圖片就是標籤。
這些選單會退化成一整欄空白的列,而且點擊依然有反應。選單保有原本的高度、分隔線與可點擊區域,因此在自動化檢測的眼中,它看起來根本不像渲染失敗。一個斷言「選單有六個項目」的 UI 測試照樣通過。截圖比對抓得到這件事,項目數量的斷言抓不到。
真正的家族相似之處在於它的安靜。macOS 27 也會在不詢問的情況下拒絕跨團隊容器存取——API 回傳一個看起來完全正常的 URL,失敗要等到實際讀取時才浮現。兩項變動都以沉默取代了原本可見的訊號,也都以「看起來不像它真正的樣子」的形式現身。
三種框架,三種修正
| 框架 | API | 值 |
|---|---|---|
| AppKit | NSMenuItem.preferredImageVisibility |
.automatic、.visible、.hidden |
| UIKit | UIMenuElement.preferredImageVisibility |
.automatic、.visible、.hidden |
| SwiftUI | labelStyle(.titleAndIcon) |
一種標籤樣式,不是列舉 |
AppKit 與 UIKit 的形式一致。兩個屬性都接受 ImageVisibility 列舉,值為 .automatic、.visible 與 .hidden,兩者都以 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 走的是另一條路。其發行說明寫道:「請搭配 .titleAndIcon 樣式使用 labelStyle(_:) 檢視修飾器,以表明選單項目 Label 的圖示應始終顯示。」5
Menu("File") {
Button {
openDocument()
} label: {
Label("Open Document", systemImage: "doc")
}
.labelStyle(.titleAndIcon)
}
另外請注意,SwiftUI 的預設值對齊的是 AppKit 的基準行為,而非 27 SDK 的行為:符號圖片隱藏,非符號圖片仍然可見。5上面那張 SDK 連結對照表描述的是 AppKit,別想當然耳地套到 SwiftUI 上。
影響範圍比聽起來窄
平台的措辭要細讀,因為各則條目的寫法並不相同。
UIKit 那一則涵蓋 iPadOS 27.0 與 macOS 27.0 上的「選單列與快捷選單」。4SwiftUI 那一則更具體:iPadOS 27.0 與 macOS 27.0 的選單列,「以及 macOS 27.0 上的快捷選單」。5iPadOS 上的 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 都持續為「設定」、「分享」、「列印」這類全系統通用的選單項目提供預設可見的圖片。14SwiftUI 亦然。5
實際的後果是診斷上的混淆。您更新後打開選單,看到「設定」與「分享」旁邊有圖示,自家項目旁邊卻沒有。合理的推論是圖片載入失敗、資產目錄壞了,或是符號名稱寫錯了。但這些事一件都沒發生,系統只是在套用一套豁免少數知名項目的政策。
決定要保留哪些圖示
五則發行說明條目無一例外,都要開發者參閱更新後的 Human Interface Guidelines,據以決定哪些選單項目仍應顯示圖片。145這份指引究竟怎麼說,我無法驗證:HIG 的選單頁面採用用戶端渲染,抓取工具幾乎取不到任何文字,而且 HIG 內容也沒有像 API 參考文件那樣的 JSON 端點。請自己去確認,不要輕信任何摘要的說法——包括這一篇。
發行說明本身唯一提供的具體判準來自 SwiftUI 那一則:當選單項目「代表的是一個物件或一個概念,而非一項動作」時,建議顯示圖示。5
這條規則堪用。列出開啟中文件、可用裝置或已存篩選條件的選單,命名的是物件,圖示在那裡承載了辨識身分的功能。而動詞構成的選單——也就是絕大多數選單——每一列旁邊擺個圖示並不會多出什麼價值。Apple 顯然認定 macOS 26 把圖片用得太浮濫,而 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 條目中有兩則歸類為問題修正,這意味著這項行為在 beta 週期中已經改過一次。我在 2026年8月1日對照 Beta 4 的說明重新驗證過全部五則,內容與此處引述一致。在依據其中任何一項行動之前,請對照當前的說明再確認一次。
稽核既有的程式碼庫
這項變動夠機械化,足以有系統地稽核,而且值得在重新建置之前就做,而不是等測試人員回報選單一片空白之後才做。
從最嚴重的情況開始查。帶有圖片卻標題為空的 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'
這兩種樣式都不夠周全,因為標題可能三行之後才設定,也可能是從本地化字串表讀來的。請把結果當成待檢查的候選清單,而不是結論。
接著查 xib。「macOS 26.0 only」核取方塊沒有任何 grep 幫得上忙,它藏在選單項目檢閱器裡,而不在任何建置過程看得見的屬性中。如果您的選單出自 Interface Builder,稽核就意味著逐一打開每個選單、檢查每個項目。
再來是 UIKit 的選單建構器。UIMenu、UIAction、UICommand 與 UIKeyCommand 都新增了接受 preferredImageVisibility 的初始化器,因此修正可以直接寫在建構當下,不必事後再補上一行指派。4
然後是選單內的 SwiftUI Label 用法。這些最容易漏掉,因為選單裡的 Label 在原始碼中看起來和其他地方的 Label 一模一樣。修飾器要加在標籤上,而且只加在您希望保留圖示的地方。
建置兩次並比對。最可靠的檢查根本不必讀程式碼。分別對 26 SDK 與 27 SDK 建置,打開同一批選單,兩邊都拍下來。同一份原始碼產出兩種不同的選單,正是這項變動的重點所在,而並排比對找得到 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 不是您該用的 API。請在 Label 上使用 labelStyle(.titleAndIcon)。
- SwiftUI 的預設值隱藏符號圖片、保留非符號圖片,對齊的是 AppKit 的基準行為,而非 27 SDK 的行為。
常見問題
為什麼「設定」與「分享」還有圖示?
系統豁免了特定的通用選單項目。AppKit、UIKit 與 SwiftUI 都持續為「設定」、「分享」、「列印」這類項目提供預設可見的圖片。145看到那些圖示還在、自家的卻不見了,是預期中的行為,不是載入失敗。
停留在較舊的 SDK 就能避開嗎?
只能避開一部分,而這個區別很重要。連結 macOS 26.0 及後續 SDK 的 App 已經會隱藏符號圖片。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,而我無法直接讀取該文件。Apple 在 SwiftUI 那一則中給出的判準是:當選單項目「代表的是一個物件或一個概念,而非一項動作」時顯示圖示。5
資料來源
-
Apple,“macOS 27 Golden Gate Beta 4 Release Notes,” AppKit。Radar 170477566:
NSMenu預設隱藏所有選單項目符號圖片,非符號圖片維持可見;適用於連結 macOS 26.0 及後續 SDK 的應用程式;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 在多數情境下預設隱藏所有選單項目符號圖片,非符號圖片維持可見;
labelStyle(_:)搭配.titleAndIcon;當選單項目「代表的是一個物件或一個概念,而非一項動作」時顯示圖示的建議;通用系統項目的預設可見圖片。 ↩↩↩↩↩↩↩↩↩ -
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 起可用。 ↩↩↩