工程師第一次使用 Xcode 建構設定時要注意的核心概念解析

Published on: | Last updated:

這可能是你聽過最大的誤解:Xcode Build Settings 不是「哪邊看到就改哪邊」,它是有層級、有優先序的合併系統。用 Levels 看的時候,設定值從右往左解析,Target Settings 壓過 Project Settings,最後在 Resolved 變成編譯器真的會吃的那一份。

  • 看診斷:Build Settings 用 Levels,不要只看 Combined
  • 記方向:解析方向右 → 左,Resolved 在最左邊
  • 抓兇手:看哪一欄被 highlight,誰亮誰負責
  • 不要硬蓋:要加值用 $(inherited),不然你是在清空
  • 減少噪音:共用值丟到 .xcconfig,少在 UI 點來點去
圖片 1 前段總覽:Xcode Build Settings 的解析方向和欄位優先序
圖片 1 前段總覽:Xcode Build Settings 的解析方向和欄位優先序

你以為你在改設定 其實你在改優先權

Xcode Build Settings 的 Levels 視圖把設定拆成多欄,代表不同來源。Resolved(最終值)是 build system 實際使用的結果,highlight 的那格就是當下勝出的來源,不是「看起來順眼」的那個欄位。

很多人卡住是因為只盯著 Combined。Combined 很像「報表」。漂亮。也很容易讓你誤判。

Levels 才是現場監視器。你要找誰把值蓋掉,或誰忘了繼承,這邊一眼就看出來。

講到這個我就想到一種很常見的災難:你以為改了 Target 的某個值,CI 卻還是吃另一個值。然後你開始懷疑人生,懷疑 Xcode,懷疑 Apple。

其實只是你改的那欄根本沒贏。

就這樣。

Filters 跟 Display 不是裝飾 你選錯就會看錯

Xcode Build Settings 有兩種控制:Filter 決定你看到哪些設定,Display Mode 決定你看到的是結果還是來源。Basic 只顯示常改的項目,Customized 只顯示你有改過的項目,All 會把預設值與繼承值全部攤開。

Filters 這邊真的會害人。

你開 Basic,看不到某些關鍵設定。你以為不存在。它其實在 All 裡面安靜躺著,還贏了。

Display Mode 更是。

  • Combined:只看最後的 Resolved 值。快。也最容易被騙。
  • Levels:把每一層來源列出來。慢一點。省掉你半天亂猜。

如果你現在是在追 build error 或 signing 亂跳,真的拜託先切 Levels。

手不要抖。

圖片 2 中段核心拆解:Filters 與 Display Mode 的決策樹
圖片 2 中段核心拆解:Filters 與 Display Mode 的決策樹

Levels 欄位拆解 右邊越新越兇

Levels 的每一欄代表一個來源層級,越靠右優先權越高。iOS Default 是 Xcode 的平台預設,.xcconfig 是文字設定檔,Project Settings 是專案層級 UI 值,Target Settings 是目標層級 UI 值,最後由 Resolved 顯示編譯實際使用值。

欄位大致就這幾種:

  • iOS Default:Xcode 給的平台預設。你沒碰它它也會存在。
  • Project Config file:專案的 .xcconfig。文字檔。好追 diff。
  • Project Settings:專案層級的 UI 設定。最容易被人手滑。
  • Target Config File:特定 target 的 .xcconfig。拆多 target 時會用到。
  • Target Settings:target 層級 UI 設定。優先權很高。也很容易把東西蓋死。
  • Resolved:左邊那個最後答案。編譯器認的那個。

原文那個 iOS Deployment Target 的例子其實很好用。

iOS Default 是 iOS 26。Project 的 config file 把它改成 iOS 15。Target 又把它改成 iOS 17。Resolved 就會是 iOS 17。

這種 override 在多 target 很常見。

像 Live Activities 這種 extension,最低系統版本要求常常比主 App 高。你不分開設就會撞牆。

圖片 3 轉折比較:同一個設定值在不同層級被覆寫的樣子
圖片 3 轉折比較:同一個設定值在不同層級被覆寫的樣子

highlight 不是漂亮配色 它是在指認犯人

Levels 裡的 highlight 代表該設定目前被採用的來源,也就是 Resolved 追溯回去的那一格。刪掉某一層的 override,highlight 會往下一個可用來源移動,讓你確認「誰在接手」。

這功能超適合拿來做「刪除實驗」。

你懷疑 target 那格在亂蓋?把那一行在 target 裡 Delete 掉。看 highlight 有沒有跳去 Project Config file 或 iOS Default。

跳了。那就對了。

沒跳。你就知道還有別的地方在蓋你。

順便講個小雷。

有些設定你以為只在 UI 控,實際上你在 build arguments、環境變數也能蓋過去。CI 常見。local 不一定。

這種問題不會在你「盯著 Combined」時自己浮出水面。

$(inherited) 是保命符 不用就等著被你自己害死

$(inherited) 是 Xcode 的繼承關鍵字,用來把目前層級解析到的值保留下來,再加上你在這一層新增的內容。Other Swift Flags 這類會累加的設定,目標層級要加旗標時放 $(inherited),避免把專案層級的旗標整包覆蓋掉。

Other Swift Flags 這種欄位,真的一堆人寫成「我只想加一個 -Dxxx」。

然後直接把原本的 flags 全清空。

編譯當然怪。

正確做法就很土。很直白。

$(inherited) -DNEW_FLAG

你要加值。不是要換血。

講到變數,我腦中會自動跳出 $(CONFIGURATION)$(SRCROOT)。這兩個在組路徑、分 Debug/Release 的時候很常用。

不過這種東西一旦你開始玩,很容易把設定玩成密室逃脫。

自己看得懂就好。真的。

台灣通路避雷指南 你在 UI 點設定是在自找麻煩

在台灣常見的團隊協作場景,Build Settings 最容易炸的點不是技術,是通路與流程:專案在不同人手上、不同 Mac、不同 CI 平台跑,UI 設定一多就開始出現「我這台可以你那台不行」。把共用設定集中到 .xcconfig,Git diff 乾淨,Review 也比較像人類能看的東西。

這段講白了就是「內行人怎麼避雷」。

  • 連鎖賣場式開發:多人一起點 Xcode UI。設定散在 Project/Target。最後每次改 Signing 都像拆炸彈。
  • 藥局式開發:只買你需要的。共用的值放 shared .xcconfig。target 只留差異。乾淨。
  • 網購平台式開發:CI/CD 一路跑。環境變數或 build arguments 會蓋設定。你沒把來源列清楚,就會被「同一份 code 不同結果」搞到心態崩。

價位區間我用一個很粗的說法。

小團隊或接案,通常沒人想花「一兩天」整理設定。因為看不到立即產出。

中型以上,出一次大包就會開始覺得:整理設定其實比追 bug 便宜。

提示:真的要做「集中化」,把共用值放在最右邊那個你打算長期維護的層級,通常是 shared .xcconfig。不要每層都留一份一樣的值。那不是備援。那是噪音。

你會在版本控制看到一堆無意義的 diff。

你會在 code review 看到一堆無意義的討論。

然後你會開始討厭改設定。

圖片 4 結尾前總結:把共用設定集中到 xcconfig 的前後對照
圖片 4 結尾前總結:把共用設定集中到 xcconfig 的前後對照

FAQ 直答區

規則:每題只給能直接用在排查的答案,不講故事。

Levels 跟 Combined 我該看哪個

追問題用 Levels,確認最後值用 Combined;Levels 能看出設定來源與 override 鏈,Combined 只顯示 Resolved 結果。

highlight 代表什麼

highlight 代表該層級的值目前贏了,會被帶到 Resolved 成為實際編譯使用值;刪掉那層 override,highlight 會移到下一個來源。

什麼時候一定要用 $(inherited)

會累加的設定就用,例如 Other Swift Flags、Header Search Paths;你在 target 想加一段值時放 $(inherited),避免把 project 或 xcconfig 先前的值整包覆蓋。

為什麼我刪了 target 的設定 還是沒變

因為同一個 key 可能在 Project Settings、.xcconfig、或 build arguments/環境變數仍有 override;切到 Levels 找 highlight 的那欄就能定位來源。

xcconfig 到底值不值得導入

多 target、多人協作、CI 會吃環境變數的專案就值得;.xcconfig 把共用設定文字化,diff 好看、可重用、也比較不會被 UI 手滑污染。

結論金句:Xcode Build Settings 不是「設定清單」,是「優先序系統」,你把共用值集中到 .xcconfig,就會少掉一堆人為噪音。

好,最後問你一個很實際的。

你現在的專案是「每個 target 都一堆重複設定」那種,還是「shared xcconfig 一份控住大局」那種?你最常被哪個設定坑,Signing、Deployment Target,還是 flags?

Related to this topic:

Comments

撥打專線 LINE免費通話