Apple 的 Xcode 27.2 Beta 2 發布說明 將「Mac Catalyst 使用 iOS 27.1 專屬 API 時發生編譯錯誤」列為已知問題,並提供條件編譯規避方式。症狀 → 最快解法:若同一提交只有 Mac Catalyst 失敗,且錯誤指向 iOS 27.1 API,先按 API 所屬平台隔離程式碼,再分別重建 iOS 與 Catalyst;若錯誤不符合這些條件,請先查依賴、建置設定與原始碼,不要直接歸咎於 Xcode 或遠端節點。
適合維護 iOS 與 Mac Catalyst 共用程式碼、需要釐清平台 API 邊界的開發者。
也適合負責 Xcode CI 的工程師,以及要在實際建置節點重現失敗的 DevOps 工程師。
最後更新於 2026 年 10 月 9 日;版本問題狀態核實自 Apple 的 Xcode 27.2 發布說明及 Xcode 27.1 發布說明。
SECTION 01先確認錯誤是否符合已知問題
Apple 記錄的是特定版本狀態與特定錯誤條件,不是所有 Mac Catalyst 編譯失敗的通用解釋。你要先把問題縮小到「建置目標」和「出錯 API」:錯誤若只在 Catalyst 出現,且編譯器找不到的符號屬於 iOS 27.1 API,才適合先試發布說明中的條件編譯規避方式。這個記錄不能推論問題必然出現在所有專案,也不能推論後續 Xcode 版本仍未修正。
為什麼 Xcode 27.2 建置 Mac Catalyst 時會找不到 iOS 27.1 API?
可能原因是程式碼引用了 iOS 專屬 API,但該段程式碼也被編入 Mac Catalyst 目標。此時編譯器在目前目標的平台環境中解析符號,若 API 不適用於該目標,就可能出現 undeclared identifier、not found 或 cannot find 一類錯誤。這只是符合已知問題的線索;符號拼寫錯誤、SDK 不一致或依賴版本差異也可能造成相似訊息。
先保存完整錯誤行、出錯檔案、符號名稱與建置目標,再確認錯誤來自 App Target、共用模組還是第三方依賴。不要只看錯誤摘要,也不要以單一錯誤字串就判定根因。Apple 的 Mac Catalyst 應用程式文件可用來核對 Catalyst 的平台模型;符號本身則要回到相應 API 文件確認其平台可用性。
SECTION 02用相同提交劃清平台邊界
使用同一份程式碼、相同依賴解析結果,分別建置 iOS 與 Mac Catalyst。若 iOS 成功而 Catalyst 失敗,先比較兩個目標的 SDK、Build Settings、編譯條件與依賴版本;接著確認錯誤符號是否為 iOS 專屬 API。iOS 成功只能說明該目標通過,不能單獨證明是平台 API 問題。
iOS 建置通過、Catalyst 失敗,怎麼判斷是不是平台 API 問題?
檢查失敗是否穩定重現於 Catalyst,並在原始碼或依賴中定位出錯符號。若該 API 僅供 iOS 使用,而且錯誤發生在 Catalyst 編譯階段,平台邊界就值得優先檢查;若兩個目標都失敗,或只有乾淨建置、特定依賴更新後才失敗,則應先排查共享程式碼、SDK 與設定差異。
不要把「本機重試後成功」當作根因證據。保留失敗與成功建置的完整日誌,連同提交識別、Xcode 版本、SDK 和目標平台一起比較,才能分辨環境變更與程式碼修正的影響。
| 觀察結果 | 優先檢查 | 暫時不要下的結論 |
|---|---|---|
| 只有 Catalyst 失敗,錯誤指向 iOS 專屬符號 | API 平台可用性、編譯條件 | 所有 Catalyst 程式碼都有問題 |
| iOS 與 Catalyst 都失敗 | 符號宣告、SDK、依賴與共同設定 | 必定是已知平台問題 |
| 只有特定工作目錄或節點失敗 | 依賴解析、快取、建置設定差異 | 遠端 Mac 硬體效能不足 |
| 錯誤來自無法修改的依賴 | 依賴版本、維護狀態與目標支援 | 在 App 層排除整段程式碼就已修好 |
SECTION 03以編譯期條件隔離平台程式碼
Mac Catalyst 的 iOS 專屬程式碼怎麼用條件編譯隔離?
Swift 可用 #if !targetEnvironment(macCatalyst) 包住只供 iOS 使用的程式碼;Objective-C 則可用 #if !TARGET_OS_MACCATALYST。實際條件要按 API 所屬平台和專案目標選擇,並確認另一個平台仍有合理的替代實作或清楚的功能邊界。Apple 的 Swift 條件編譯說明與 Xcode Build Settings 參考可協助核對語法與建置條件。
| 語言或位置 | 編譯期檢查方式 | 適用情況與注意事項 |
|---|---|---|
| Swift | #if !targetEnvironment(macCatalyst) |
將僅供 iOS 的宣告或呼叫排除於 Catalyst 編譯之外;需確認被排除後仍有可編譯的程式路徑 |
| Objective-C | #if !TARGET_OS_MACCATALYST |
在預處理階段區隔平台程式碼;檢查巨集條件是否與實際建置目標一致 |
| 共用模組 | 依模組支援的平台設計條件 | 避免讓 App Target 的修補意外改變其他使用者或其他目標的行為 |
不要用執行階段的 if 取代編譯期隔離:如果編譯器在建置階段已無法解析 API,程式根本無法進入執行階段判斷。也不要為了讓 Catalyst 通過,就把整個功能區塊排除,卻沒有核對 iOS 功能是否仍保留、Catalyst 是否需要替代行為。修正範圍應盡量貼近不相容的 API 呼叫,並讓程式碼審查者看得出平台差異的理由。
操作流程:
- 記下錯誤符號、檔案位置,以及失敗的建置目標。
- 在專案原始碼與依賴中定位符號宣告和呼叫點,確認 API 的平台歸屬。
- 對同一提交執行 iOS 與 Mac Catalyst 建置,保存兩邊使用的 SDK、Xcode 版本及完整日誌。
- 依語言加入編譯期條件,將不適用的 API 呼叫限制在支援它的平台;若共享模組被多個目標使用,先確認條件的作用範圍。
- 檢視被隔離程式碼的功能路徑,確認 iOS 沒有被一併排除,Catalyst 也沒有留下未實作的呼叫或型別引用。
- 重新建置兩個目標;若專案有測試或封存流程,再執行相應驗收,並將修正與日誌一併保存。
SECTION 04追查共用程式碼與依賴的影響面
條件編譯放在不同層級,影響範圍也不同。若錯誤位於 App Target,修補通常較集中;若位於共用模組,使用該模組的其他平台可能受到影響;若來自第三方依賴,App 層的排除條件未必能阻止依賴自身編譯失敗。先找出實際失敗的 target 與檔案歸屬,再決定在哪一層修改。
對無法修改的依賴,記錄套件名稱、解析版本、錯誤符號與失敗目標,接著比較升級、替換或暫緩納入的風險。不要只為了讓 Catalyst 通過而直接移除整個依賴功能,尤其該依賴同時服務 iOS 目標時。若採用條件編譯,重點是確認兩個平台的依賴圖與功能路徑仍符合預期。
SECTION 05決策條件與雙目標驗收
| 判斷條件 | 建議處理 | 驗收依據 |
|---|---|---|
| Catalyst 單獨失敗,且符號確屬 iOS 專屬 API | 依 Apple 記錄加入適當的編譯期隔離 | 同一提交下,iOS 與 Catalyst 都完成建置 |
| 兩個目標都失敗,或符號平台歸屬不明 | 回退至符號、SDK、依賴及設定差異排查 | 能以錯誤位置和日誌解釋根因 |
| 失敗源自不可修改的依賴 | 評估升級、替換或暫緩該依賴 | 依賴版本與支援目標已記錄,兩個目標均復測 |
| 後續 Xcode 版本疑似修正問題 | 先核對該版本官方說明,再移除暫時條件並復測 | 官方狀態與專案實際結果都支持移除 |
修復後,遠端 Mac CI 要重新驗收哪些目標?
在實際負責 Apple 工具鏈工作的 Mac 執行環境上,使用同一提交分別跑 iOS 與 Mac Catalyst 建置;如果工作流程包含測試或封存,也分別確認相應結果與產物。保存 Xcode 版本、SDK、目標平台、提交識別和完整失敗日誌。只看到本機一次建置通過,不足以關閉 CI 故障。
Apple 的分發與封存說明及註冊裝置分發文件可協助你核對專案實際採用的交付流程。若團隊只要求編譯,驗收範圍不必擴張成完整發布;若 CI 會產出測試或分發用建置,則應把這些產物也納入對應目標的驗收紀錄。
目前手邊的方案若只靠 Linux 建置節點,便無法直接執行 Xcode 的 macOS 工具鏈;若共用個人 Mac,建置環境會依賴該台裝置的設定與可用狀態;若只憑本機成功關閉 CI 告警,則可能漏掉節點上的 SDK 或依賴差異。若你需要短期重現或隔離一個 macOS 建置環境,MACNOX 遠端 Mac 租用可作為本地與 CI 之間的另一種測試方式;實際是否合適,仍要以你的建置頻率、權限需求和驗收方式判斷。你可先查看 MACNOX 方案與租用週期,再按需求了解租用流程。若日常長期高頻建置或需要直接連接本機周邊,先比較自有 Mac 與現有 CI 節點的總體維護方式,再決定是否需要額外的遠端執行環境。
遇到 Xcode 27.2 Mac Catalyst 編譯失敗,先確認錯誤是否只發生在 Catalyst,並核實符號是否為 iOS 27.1 專屬 API;符合條件才採用編譯期隔離。若後續 Xcode 版本的官方說明更新了問題狀態,先依說明與專案復測結果判斷,再移除暫時規避。