# App Store Connect 建置號碼與版本號

> 版本號是顧客看到的號碼，建置號碼用來識別每次上傳。兩者的組合必須唯一，用 Expo 的話，EAS 會幫你遞增建置號碼。

原始頁面：[App Store Connect 建置號碼與版本號](https://devoria.fr/zh-hant/blog/app-store-connect-build-number-version)
作者：[Mehdi Azizi](https://devoria.fr/zh-hant/mehdi-azizi)
發布日期：2026-11-04
內容最後修訂：2026-11-04


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 的文件](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleshortversionstring)把它描述為使用者看得到的版本：由句點分隔的三個整數，例如 10.14.1。[關於 CFBundleVersion 的文件](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion)講的則是建置版本：一到三個整數，只能包含數字和句點。

| 項目     | iOS 鍵                     | 誰看得到   | Expo 欄位         |
| -------- | -------------------------- | ---------- | ----------------- |
| 版本號   | CFBundleShortVersionString | 你的顧客   | `version`         |
| 建置號碼 | CFBundleVersion            | 你和 Apple | `ios.buildNumber` |

虛構的例子：針對 1.4.0 版，你在測試期間上傳了建置 12、13 和 14，再從中挑一個送審。[App Store Connect 說明文件](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds)是這樣總結的：版本號把建置連結到它的頁面，建置號碼則在整個系統中識別它。

## Apple 的遞增規則

1. **組合必須唯一。**根據 [Xcode Cloud 的文件](https://developer.apple.com/documentation/xcode/setting-the-next-build-number-for-xcode-cloud-builds)，App Store Connect 要求版本號和建置號碼的組合是唯一的。所以 iPhone App 在新版本可以從 1 重新開始。Mac App 不行：它的號碼必須一直往上。
2. **已核准的版本就封閉了。**Apple 一旦核准 1.4.0 版，你就不能再為它加建置。下一版必須用更高的號碼。
3. **每個數字都以整數比較。**1.10 排在 1.9 之後，因為 10 比 9 大。在已核准的 1.20 之後上傳 1.9 版，會被拒絕。

我的建議：**用一個永遠往上的整數建置號碼，不要歸回 1。**iPhone 上允許從 1 重來，但在 App 整個生命週期中都唯一的號碼，可以避免在 TestFlight 裡搞混兩個建置。我那些用遠端模式的 App 就是這樣：計數器會從一個版本延續到下一個版本。

## 用 Expo 和 EAS 管理版本號與建置號碼

[Expo 關於版本的頁面](https://docs.expo.dev/build-reference/app-versions/)（2026 年 9 月 25 日更新）把角色分開。版本號（app.json 裡的 `version`）由你負責：準備新版發布時再改。建置號碼（`ios.buildNumber`）可以交給 EAS。Expo 也提到，忘記遞增建置號碼是上傳被拒的常見原因。

全部在 eas.json 裡設定：

```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 參考文件](https://docs.expo.dev/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：版本已經核准

訊息大概長這樣（號碼為虛構）：

```text
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 設定參考文件](https://docs.expo.dev/versions/latest/config/app/)，它在 iOS 上會覆蓋 `version`。相近的錯誤 ITMS-90186「Invalid Pre-Release Train」也是同樣的解法，它代表這個版本已經不接受新的建置。

## ITMS-90189：Redundant Binary Upload

這次卡住的是建置號碼：

```text
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」：你的建置沒有出現

建置已經送出，但你的頁面上就是選不到它。依序檢查以下幾點。

1. **它還在處理中。**Apple 會先處理每個建置才顯示出來，處理完會寄 email 給你。[Expo](https://docs.expo.dev/submit/ios/) 說一般需要 10 到 15 分鐘。[根據 Apple](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata)，處理超過 24 小時就要透過 Feedback Assistant 開單。
2. **它在等你的加密聲明。**這就是 Missing Compliance 狀態，下面會詳細說明。
3. **版本號對不上。**在 App Store Connect 裡，1.4.1 的建置不會出現在你準備為 1.5.0 的頁面下。把兩者對齊。
4. **這段期間有版本發布了。**根據[選擇建置的說明](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit)，這時清單只會顯示那次發布之後上傳的建置。
5. **是測試人員看不到。**在 TestFlight App 裡，「no builds available」通常代表建置不在任何群組裡、正在等 Beta 審查，或已經過期。詳情請看[用 TestFlight 測試你的 iPhone App](https://devoria.fr/zh-hant/blog/testflight-test-iphone-app-before-review)。

### 你該知道的狀態

以下是根據 [Apple 的清單](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses)，最常導致建置不見的狀態。Processing 和 Failed 不在那份清單裡：它們是[建置追蹤](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata)中描述的上傳狀態。

| 狀態               | 代表什麼           | 你的修正方式            |
| ------------------ | ------------------ | ----------------------- |
| Processing         | Apple 正在處理建置 | 等 email                |
| Failed             | 處理時發生錯誤     | 看錯誤訊息，重新上傳    |
| Missing Compliance | 未聲明加密         | 回答問題或改 Info.plist |
| Invalid Binary     | 上傳內容不符規定   | 修正後重新建置          |
| Expired            | 超過 90 天         | 重新建置                |
| Ready to Submit    | 可以測試或送審     | 把它加入群組            |

### 一次搞定加密聲明

沒有 `ITSAppUsesNonExemptEncryption` 這個鍵的話，[Apple](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) 每次新版本都會問你合規問題。在 Expo 裡，這個欄位叫 `ios.config.usesNonExemptEncryption`：

```json
{
  "expo": {
    "ios": {
      "config": {
        "usesNonExemptEncryption": false
      }
    }
  }
}
```

`false` 的意思是：沒有使用加密，或只使用豁免的加密。[Apple 說明](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations)，系統內建的加密（例如 HTTPS 連線）一般是豁免的，而且你的回答也涵蓋你用的函式庫。我的三個 App 都聲明 `false`。**只有在你的 App 確實如此時才填 `false`：這份聲明是有約束力的。**

## 已經上傳的建置可以改號碼嗎？

不行。號碼寫在已簽署的二進位檔裡：要修正就得重新建置。

你能改的是連結到版本的那個建置。Apple 規定每個版本只能有一個建置，但在送審之前，[你想換幾次都可以](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit)：

1. 在 App Store Connect 打開該版本，進入 Build 區塊。
2. 滑鼠移到目前的建置上，點刪除按鈕，也就是減號。
3. 點新增按鈕，也就是加號，選擇正確的建置，然後儲存。

把建置從版本移除，並不會把它從你的帳號刪掉。如果版本已經在審查中，[先撤回送審](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/remove-a-submission-from-review)：審查會從頭開始。

## 下次上傳之前

建置號碼只是上傳時的其中一項檢查。建置映像可能觸發 [ITMS-90725](https://devoria.fr/zh-hant/blog/itms-90725-sdk-version-issue-expo)，簽署也有它自己的陷阱，詳見 [iOS 開發者憑證與 provisioning profile](https://devoria.fr/zh-hant/blog/ios-developer-certificate-provisioning-profile-expo)。從建置到 TestFlight 的完整流程，請看[沒有 Mac 也能發布 iOS App](https://devoria.fr/zh-hant/blog/publish-ios-app-without-mac-expo-eas)，審查時間則在 [App Store 審核要多久](https://devoria.fr/zh-hant/blog/app-store-review-time)。所有步驟都整理在[把 App 發布到 App Store](https://devoria.fr/zh-hant/expertise/publish-app-on-app-store) 這一頁。

如果你正在準備第一次上架，[來做免費診斷](https://devoria.fr/zh-hant/diagnostic)：它會告訴你專案卡在哪裡，並寄給你我的 Apple 防退件檢查清單。要打造 App、串接訂閱並發布，[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios) 會帶你走完四個步驟，附上我自己 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 會要求你開單。


## 你的專案

[Review Kit](https://devoria.fr/zh-hant/kits/app-review)：我的 App Store 審查檢查清單、我被 Apple 退件後的修正、Google Play 檢查清單，以及三個 Claude Code skill。$1,749。

[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android App：我自己 App 的起始程式碼、上架商店的完整流程，以及所有套件。$3,599。

[診斷：你離自己的 iPhone App 還差什麼](https://devoria.fr/zh-hant/diagnostic)：7 個問題，60 秒：找出真正卡住你發布 iPhone App 的原因，拿到你的 4 步驟路線，以及最適合你的套件。
