App Store Connect 建置號碼與版本號
作者:Mehdi Azizi
發布於 ,8 分鐘
版本號是顧客看到的號碼,建置號碼用來識別每次上傳。兩者的組合必須唯一,用 Expo 的話,EAS 會幫你遞增建置號碼。
App Store Connect 的 build number 就是建置號碼,也就是 CFBundleVersion 這個鍵,用來識別每一次上傳。版本號 CFBundleShortVersionString 則是顧客在 App Store 上看到的號碼。Apple 要求版本號和建置號碼的組合必須唯一:同一個版本下,一個建置號碼只能用一次。
用 Expo 的話,版本號由你自己設定,EAS 可以在每次正式版建置時自動遞增建置號碼。這篇指南會說明這兩個號碼、Apple 的規則、ITMS-90062 和 ITMS-90189 錯誤,以及建置沒出現時該檢查什麼。
我用 Expo 和 EAS 發布自己的 iOS App,包括 Solys、TradaZen 和 Nolera。下面展示的設定,就是它們 eas.json 檔案裡的設定。
版本號和建置號碼有什麼差別?
Info.plist 裡有兩個鍵用來識別你的 App。Apple 關於 CFBundleShortVersionString 的文件把它描述為使用者看得到的版本:由句點分隔的三個整數,例如 10.14.1。關於 CFBundleVersion 的文件講的則是建置版本:一到三個整數,只能包含數字和句點。
| 項目 | iOS 鍵 | 誰看得到 | Expo 欄位 |
|---|---|---|---|
| 版本號 | CFBundleShortVersionString | 你的顧客 | version |
| 建置號碼 | CFBundleVersion | 你和 Apple | ios.buildNumber |
虛構的例子:針對 1.4.0 版,你在測試期間上傳了建置 12、13 和 14,再從中挑一個送審。App Store Connect 說明文件是這樣總結的:版本號把建置連結到它的頁面,建置號碼則在整個系統中識別它。
Apple 的遞增規則
- 組合必須唯一。根據 Xcode Cloud 的文件,App Store Connect 要求版本號和建置號碼的組合是唯一的。所以 iPhone App 在新版本可以從 1 重新開始。Mac App 不行:它的號碼必須一直往上。
- 已核准的版本就封閉了。Apple 一旦核准 1.4.0 版,你就不能再為它加建置。下一版必須用更高的號碼。
- 每個數字都以整數比較。1.10 排在 1.9 之後,因為 10 比 9 大。在已核准的 1.20 之後上傳 1.9 版,會被拒絕。
我的建議:用一個永遠往上的整數建置號碼,不要歸回 1。iPhone 上允許從 1 重來,但在 App 整個生命週期中都唯一的號碼,可以避免在 TestFlight 裡搞混兩個建置。我那些用遠端模式的 App 就是這樣:計數器會從一個版本延續到下一個版本。
用 Expo 和 EAS 管理版本號與建置號碼
Expo 關於版本的頁面(2026 年 9 月 25 日更新)把角色分開。版本號(app.json 裡的 version)由你負責:準備新版發布時再改。建置號碼(ios.buildNumber)可以交給 EAS。Expo 也提到,忘記遞增建置號碼是上傳被拒的常見原因。
全部在 eas.json 裡設定:
{
"cli": {
"appVersionSource": "remote"
},
"build": {
"production": {
"autoIncrement": true
}
}
}
"remote":由 EAS 伺服器保存建置號碼。這是 EAS CLI 12 起建議的做法。計數器從你設定中的值開始,或從 1 開始,之後ios.buildNumber會被忽略。"local":以你的設定為準。搭配autoIncrement時,EAS 會修改你檔案裡的ios.buildNumber,而你每次建置後都必須 commit 這個變更。autoIncrement:eas.json 參考文件接受true或"buildNumber"來遞增建置號碼,"version"則會遞增版本號的最後一位。Expo 註明,在遠端模式下不支援"version"。
我這邊,TradaZen 和 Nolera 用 remote。Solys 還是 local:它的建置號碼存在 app.json 裡,每次正式版建置都會讓檔案裡的號碼往上。兩種都能用,但遠端模式可以消除忘記 commit 的風險。
另外還有兩個指令。eas build:version:set 用來初始化遠端計數器:輸入最後一次上傳給 Apple 的號碼。eas build:version:sync 會把遠端的值複製回你的專案,哪天你要用 Xcode 編譯時很有用。搭配 EAS Update 時,遠端模式不支援 nativeVersion 策略:Expo 建議用 appVersion。
ITMS-90062:版本已經核准
訊息大概長這樣(號碼為虛構):
ERROR ITMS-90062: This bundle is invalid. The value for key
CFBundleShortVersionString [1.4.0] in the Info.plist file must
contain a higher version than that of the previously approved
version [1.4.0].
Apple 已經核准 1.4.0 版:你不能再為它加建置。在 app.json 裡把版本號往上調,例如改成 1.4.1,然後重新建置。只改建置號碼是不夠的。
如果 version 已經更新,錯誤卻還是出現,找找看有沒有 ios.version 欄位。根據 Expo 設定參考文件,它在 iOS 上會覆蓋 version。相近的錯誤 ITMS-90186「Invalid Pre-Release Train」也是同樣的解法,它代表這個版本已經不接受新的建置。
ITMS-90189:Redundant Binary Upload
這次卡住的是建置號碼:
ERROR ITMS-90189: Redundant Binary Upload. You've already uploaded
a build with build number '12' for version number '1.4.0'.
1.4.0 (12) 這個組合在 Apple 那邊已經存在。用 Expo 時,常見原因有四個:
- **你用的設定檔沒有
autoIncrement。**如果你像 Nolera 那樣為 TestFlight 另建一個設定檔,記得把這個選項加回去。 - 遠端計數器落後了。你在手動上傳過之後才切到
remote:用 Apple 那邊最後一個已知號碼執行eas build:version:set。 - 本地模式下忘了 commit。下一次建置又從舊號碼開始。
- 你重新送了同一個二進位檔。用
eas submit時,選新的建置,不要選舊的。
修正方式永遠一樣:用更高的號碼重新建置。
「No builds available」:你的建置沒有出現
建置已經送出,但你的頁面上就是選不到它。依序檢查以下幾點。
- 它還在處理中。Apple 會先處理每個建置才顯示出來,處理完會寄 email 給你。Expo 說一般需要 10 到 15 分鐘。根據 Apple,處理超過 24 小時就要透過 Feedback Assistant 開單。
- 它在等你的加密聲明。這就是 Missing Compliance 狀態,下面會詳細說明。
- 版本號對不上。在 App Store Connect 裡,1.4.1 的建置不會出現在你準備為 1.5.0 的頁面下。把兩者對齊。
- 這段期間有版本發布了。根據選擇建置的說明,這時清單只會顯示那次發布之後上傳的建置。
- 是測試人員看不到。在 TestFlight App 裡,「no builds available」通常代表建置不在任何群組裡、正在等 Beta 審查,或已經過期。詳情請看用 TestFlight 測試你的 iPhone App。
你該知道的狀態
以下是根據 Apple 的清單,最常導致建置不見的狀態。Processing 和 Failed 不在那份清單裡:它們是建置追蹤中描述的上傳狀態。
| 狀態 | 代表什麼 | 你的修正方式 |
|---|---|---|
| Processing | Apple 正在處理建置 | 等 email |
| Failed | 處理時發生錯誤 | 看錯誤訊息,重新上傳 |
| Missing Compliance | 未聲明加密 | 回答問題或改 Info.plist |
| Invalid Binary | 上傳內容不符規定 | 修正後重新建置 |
| Expired | 超過 90 天 | 重新建置 |
| Ready to Submit | 可以測試或送審 | 把它加入群組 |
一次搞定加密聲明
沒有 ITSAppUsesNonExemptEncryption 這個鍵的話,Apple 每次新版本都會問你合規問題。在 Expo 裡,這個欄位叫 ios.config.usesNonExemptEncryption:
{
"expo": {
"ios": {
"config": {
"usesNonExemptEncryption": false
}
}
}
}
false 的意思是:沒有使用加密,或只使用豁免的加密。Apple 說明,系統內建的加密(例如 HTTPS 連線)一般是豁免的,而且你的回答也涵蓋你用的函式庫。我的三個 App 都聲明 false。只有在你的 App 確實如此時才填 false:這份聲明是有約束力的。
已經上傳的建置可以改號碼嗎?
不行。號碼寫在已簽署的二進位檔裡:要修正就得重新建置。
你能改的是連結到版本的那個建置。Apple 規定每個版本只能有一個建置,但在送審之前,你想換幾次都可以:
- 在 App Store Connect 打開該版本,進入 Build 區塊。
- 滑鼠移到目前的建置上,點刪除按鈕,也就是減號。
- 點新增按鈕,也就是加號,選擇正確的建置,然後儲存。
把建置從版本移除,並不會把它從你的帳號刪掉。如果版本已經在審查中,先撤回送審:審查會從頭開始。
下次上傳之前
建置號碼只是上傳時的其中一項檢查。建置映像可能觸發 ITMS-90725,簽署也有它自己的陷阱,詳見 iOS 開發者憑證與 provisioning profile。從建置到 TestFlight 的完整流程,請看沒有 Mac 也能發布 iOS App,審查時間則在 App Store 審核要多久。所有步驟都整理在把 App 發布到 App Store 這一頁。
如果你正在準備第一次上架,來做免費診斷:它會告訴你專案卡在哪裡,並寄給你我的 Apple 防退件檢查清單。要打造 App、串接訂閱並發布,iOS & Android Kit 會帶你走完四個步驟,附上我自己 App 的起始程式碼,照你的步調來。
常見問題
App Store Connect 的版本號和 build number 有什麼差別?
版本號是你這次發布的公開號碼,例如 1.4.0。build number 用來識別針對這個版本上傳給 Apple 的某一個特定二進位檔。同一個版本可以上傳好幾個建置,每個都有自己的號碼。
每次上傳都要改建置號碼嗎?
同一個版本的話,要。Apple 會拒絕版本號和建置號碼組合相同的第二次上傳,也就是 ITMS-90189 錯誤。用 EAS 時,autoIncrement 會在每次正式版建置時幫你處理。
每個新版本的建置號碼都要從 1 重新開始嗎?
不是必須的。在 iPhone 上,Apple 接受新版本使用較低的號碼,因為只有組合需要唯一。一個永遠往上的計數器還是比較好追蹤。
怎麼在 App Store Connect 修改 build number?
已經上傳的建置,號碼是改不了的。不過只要版本還沒送審,你可以從頁面的 Build 區塊替換連結到版本的建置。想要新號碼,就重新建置。
為什麼我的建置沒有出現在 App Store Connect?
最常見的原因是它還在處理中,或在等你的加密聲明。也要確認它的版本號和你頁面上的版本一致。處理超過 24 小時的話,Apple 會要求你開單。

