NOTE / 2026-09-23

From Keychain to App Store:Apple 開發全流程

以 iCodexBar 實際建置為例的 Apple 開發全流程:四種身分、簽章鏈、兩條產線、CloudKit 容器、四種發佈方式,以及做付費 App 還缺什麼。

產生時間
更新時間
來源
本地 Apple 開發筆記

以 iCodexBar 實際建置為例,拆解 Apple 開發的身分、簽章與發佈。

四種身分,先分清楚

身分本例的值管什麼誰決定
開發者 Apple IDian902792@…登入 Xcode、管理憑證與 App ID付費的那個帳號
Team ID<TEAM_ID>擁有憑證、App ID、容器。簽章時烙進 appApple 指派,不可改
Bundle IDcom.ian902792.codexbar這個 app 在全世界的唯一名字自己取,全球唯一
iCloud 帳號個人帳號資料存在誰的私有資料庫Mac/手機上登入的那個

簽章鏈:五個環節,缺一不可

多數「build failed」是這條鏈斷了一環。

憑證與 App ID 綁進 Provisioning Profile,profile 限定 entitlements 的範圍,codesign 把它們一起簽進 CodexBar.app
圖 1:五個環節如何串成簽好的 .app
  1. 憑證 Certificate

    一組公私鑰:私鑰在鑰匙圈,公鑰由 Apple 簽署。Developer ID Application: <你的名字> (<TEAM_ID>)

  2. App ID(Identifier)

    登記 bundle ID 並勾選允許的能力(iCloud、App Groups、Push…),沒勾就拿不到。com.ian902792.codexbar + iCloud + App Groups

  3. Provisioning Profile

    Apple 簽發的許可:這張憑證可簽這個 App ID、用這些能力、裝在這些裝置。嵌入 app:CodexBar.app/Contents/embedded.provisionprofile

  4. Entitlements

    plist,宣告實際要用的能力;須為 profile 允許範圍的子集,否則簽章失敗或執行時被拒。com.apple.developer.icloud-container-identifiers = [iCloud.com.ian902792.codexbar]

  5. codesign

    用私鑰簽下程式碼、entitlements 與 profile;任何位元被改,簽章即失效。codesign --verify --deep --strict

兩條產線,檔案怎麼串起來

左欄 iOS:project.yml 經 xcodegen 產生 .xcodeproj,xcodebuild 建出 .app,再用 devicectl 安裝;右欄 Mac:Package.swift 經 swift build、package_app.sh 與 codesign 產出 CodexBar.app
圖 2:iOS 與 Mac 兩條產線

Mac · SwiftPM

swift build -c release 後由 Scripts/package_app.sh 組 .app、產生 entitlements plist、嵌入 provisionprofile、codesign。可全自動,但 Info.plist、圖示等 Xcode 代勞的事都得自己做。

iOS · Xcode

xcodegen generate 從 project.yml 產生 .xcodeproj,規範禁止手改:它難審閱、易衝突,YAML 才進得了 code review。再以 xcodebuild -allowProvisioningUpdates 建置、devicectl device install 安裝。

CloudKit:容器歸團隊,資料歸使用者

Team 擁有 Container;Container 包含共用的 Public Database 與每個 iCloud 使用者各一份的 Private Database;Development schema 經 Deploy Schema Changes 推到 Production
圖 3:容器、資料庫與 schema 各歸誰
層級歸屬意義
Container
iCloud.com.ian902792.codexbar
你的 Team一個命名空間,全球唯一,不可轉移
Private Database每個 iCloud 使用者各一份A 寫的東西 B 看不到,即使同一個容器
Public Database全容器共用所有使用者讀得到,適合共用設定檔
Zone / Record Type資料結構類似資料表,欄位與索引在此定義

Development 與 Production 是兩套 schema

開發時改 Development,確認後在 Console 按 Deploy Schema Changes 推到 Production:

  • 推上 Production 不可逆:record type 刪不掉、欄位型別改不了,只能新增。
  • entitlements 的 icloud-container-environment 決定連哪一套;不一致就會「明明有寫入卻讀不到」。

四種發佈方式,怎麼選

方式簽章誰能裝效期要過審典型用途
側載 本例使用Apple Development已註冊的裝置約 1 年否自己用、開發測試
TestFlightApple 重簽最多 100 內部 + 10000 外部90 天/build內部否
外部是
beta 測試、不想接線
App StoreApple 重簽所有人無限是正式販售
Developer ID Mac 限定Developer ID
+ 公證
任何 Mac無限自動公證官網下載、Homebrew

本例的 Mac app 只走了第四種的前半:有簽章、沒公證。本機自建無 quarantine 標記,Gatekeeper 不擋;別人下載則會看到「無法打開」。

開發者後台:哪些會常用

Certificates, Identifiers & Profiles
Certificates
Development(開發機)、Distribution(上架)、Developer ID(Mac 自行分發)。私鑰只在產生它的 Mac 鑰匙圈:換機用 .p12 匯出,弄丟只能撤銷重發。
Identifiers
App IDs、App Groups、iCloud Containers、Merchant IDs(Apple Pay)、Pass Type IDs(Wallet)。
Devices
測試機 UDID;每種裝置類型每年上限 100 台,會籍週年才重置。
Profiles
Development / Ad Hoc / App Store / Developer ID。
Keys
APNs、App Store Connect API、Sign in with Apple 金鑰;.p8 只能下載一次,務必備份。
App Store Connect:上架後主戰場
My Apps
app 記錄、商店頁面、送審、版本。
TestFlight
build、測試者群組、回饋。
Pricing & Availability
定價層級、上架國家、自動換算。
In-App Purchases / Subscriptions
消耗型、非消耗型、自動續訂訂閱、優惠代碼、introductory offer。
App Analytics / Sales
安裝、留存、轉換、營收。
App Privacy
隱私營養標籤,送審必填。
Capabilities

本例用 iCloud(CloudKit)、App Groups、Push Notifications;另有 Sign in with Apple、Apple Pay、HealthKit、HomeKit、Background Modes、Keychain Sharing、Associated Domains(Universal Links)、Family Controls、Network Extensions、WeatherKit、App Attest。改了能力,profile 與 entitlements 都要更新。

往付費 App 還缺什麼

多平台

  • iPad:同一 iOS target 勾 iPad 家族;難在版面(size class、多欄、鍵盤、觸控筆)。
  • Mac:Mac Catalyst,或體驗較好的原生 SwiftUI target。
  • Watch:獨立 target,自有生命週期,效能限制極嚴。
  • Universal Purchase:同一 bundle ID 跨平台、買一次通用;須一開始規劃。

變現

  • StoreKit 2:買斷、訂閱、試用期;配 .storekit 檔可在本機模擬購買。
  • App Store Server API / Notifications:伺服器端驗證收據與訂閱、接收續訂與退款事件。
  • 抽成:標準 30%;年營收 100 萬美元以下可申請 Small Business Program 降到 15%。
  • 稅務與銀行:填完 App Store Connect 的稅表與收款帳戶才領得到錢。

審核門檻

  • Privacy Manifest(PrivacyInfo.xcprivacy):宣告收集的資料與特定 API 用途,硬性要求。
  • App Privacy 標籤:須與實際行為一致,否則被退。
  • Export Compliance:用加密就要回答(HTTPS 通常豁免)。
  • Demo 帳號:有登入就須提供給審核員。
  • 支援與隱私政策網址:皆必填且須能打開。

工程實務

  • 版本號:MARKETING_VERSION 給人看,CURRENT_PROJECT_VERSION 給 Apple 看且須遞增。
  • API 金鑰:App Store Connect API 金鑰可自動上傳,免二階段驗證。
  • fastlane 或 Xcode Cloud(Apple CI,直通 TestFlight,小專案免費):自動化截圖、上傳、版本號。
  • 崩潰蒐集:Xcode Organizer 內建,上架後先看;SDK bug 用 Feedback Assistant 回報。

錯誤訊息與它們教會的事

錯誤訊息真正的原因解法
Developer Mode disablediOS 16 起新增的閘門,預設關閉手機設定 → 隱私權與安全性 → 開發者模式 → 重開機
needs to be unlocked開發服務需要裝置解鎖才啟用解鎖並暫時關閉自動鎖定
「No profiles were found」project.yml 沒寫 CODE_SIGN_STYLE,xcodebuild 視為手動簽章,-allowProvisioningUpdates 既不註冊裝置也不建 App ID補上 CODE_SIGN_STYLE: Automatic
Device isn't registeredCODE_SIGN_STYLE 未設 → 退回手動簽章 → 自動註冊失效設成 Automatic;首次註冊仍須 Xcode GUI 跑一次
Build input file cannot be found
…mobileprovision
Xcode 快取了舊的 profile UUID清掉 DerivedData 重建
codesign 想存取鑰匙圈簽章需要私鑰,這是正常流程選「永遠允許」,否則每次建置都會卡住
rejected
source=Unnotarized Developer ID
有簽章但未公證自用無妨;要分發給別人才需 notarytool

依 2026-09-23 建置 iCodexBar 0.64.1.1 的流程整理;Apple 的版本、UI 與政策會變,以官方文件為準。