# EAS Submit iOS：把 Expo 应用发布到 App Store

> EAS Submit 只把构建上传到 TestFlight，提交审核仍需在 App Store Connect 手动完成。

原始页面：[EAS Submit iOS：把 Expo 应用发布到 App Store](https://devoria.fr/zh-hans/blog/eas-submit-ios-publish-expo-app-store)
作者：[Mehdi Azizi](https://devoria.fr/zh-hans/mehdi-azizi)
发布：2026-10-25
内容最后修订：2026-10-25


`eas submit --platform ios` 会把你的 iOS 构建上传到 App Store Connect，经 Apple 处理后出现在 TestFlight 里。**这条命令不会把你的应用提交给 Apple 审核：选择构建和提交审核，仍然要在 App Store Connect 里完成。** 想让它自动运行，需要提供应用记录的编号（`ascAppId`）和一把 App Store Connect API 密钥。

我的 iOS 应用，包括 Solys、TradaZen 和 Nolera，都是用 Expo、EAS Build 和 EAS Submit 发布的。本指南依据 [Expo 关于 iOS 提交的文档](https://docs.expo.dev/submit/ios/)，于 2026 年 10 月 25 日重新核对过。没有 Mac 的话，完整流程见 [没有 Mac 也能发布 iOS 应用](https://devoria.fr/zh-hans/blog/publish-ios-app-without-mac-expo-eas)。这里只讲上传这一步。

## 第一次运行命令前需要准备什么

Expo 列出了三个前提：

- **一个付费的 Apple Developer 账号。** 价格和注册流程见 [Apple 开发者账号](https://devoria.fr/zh-hans/blog/apple-developer-account-price-free-or-99)。
- **`ios.bundleIdentifier` 里的 Bundle ID。** 根据 [Expo 配置参考](https://docs.expo.dev/versions/latest/config/app/)，它由你自己起，但在 App Store 上必须唯一。
- **安装好 EAS CLI**，然后用你的 Expo 账号执行 `eas login`。

你还需要一个已签名的生产构建。EAS Build 会用它替你管理的证书和描述文件来生成，详见 iOS 证书与 provisioning profile。

### App Store Connect 里的应用记录：自己建还是交给 EAS？

EAS Submit 上传二进制文件的目标，必须是 App Store Connect 里已经存在的应用。

**你可以自己创建。** [Apple 的帮助文档](https://developer.apple.com/help/app-store-connect/create-an-app-record/add-a-new-app) 介绍了 New App 窗口：平台、名称、主要语言、Bundle ID、SKU 和用户访问权限。需要 Account Holder、Admin 或 App Manager 角色。

**也可以让 EAS 在第一次上传时创建。** 根据 [Expo 关于 TestFlight 的页面](https://docs.expo.dev/submit/testflight/)，你上传第一个构建时，`eas submit` 会创建应用记录。根据 [eas.json 参考](https://docs.expo.dev/eas/json/)，填写了 `ascAppId` 就会跳过这一步。名称取自 `appName`，没有的话取配置里的 `name`。主要语言取自 `language`，默认是 `en-US`。**如果你的应用首发语言是中文，请在第一次上传前设置好 `language`。**

之后，把应用记录的编号填进 `ascAppId`。Expo 说明了在哪里找：在 App Store Connect 里打开你的应用，进入 App Information，General Information 下的 Apple ID 字段就是。**它是一串数字，不是你的 Bundle ID。**

## 为什么用 API 密钥而不是 Apple ID

EAS Submit 可以用你的 Apple ID 或 App Store Connect API 密钥登录 Apple。

Apple ID 会卡在双重认证上，而 [Apple 要求](https://developer.apple.com/support/authentication/) 所有 App Store Connect 用户都开启它：每次登录都得有人确认。通过 `EXPO_APPLE_APP_SPECIFIC_PASSWORD` 传入的 App 专用密码可以绕过这一步，但 [Expo 认为它不如](https://github.com/expo/fyi/blob/main/apple-app-specific-password.md) API 密钥安全，后者是 Expo 默认且推荐的方式。**有了密钥，认证完全不需要人工介入，也就能实现自动上传。**

获取密钥有两种方式：

- **让 EAS 来管理。** 运行 `eas credentials --platform ios`，选择 `production` 配置，登录你的 Apple 账号，然后选择“App Store Connect: Manage your API Key”。
- **使用你自己的密钥。** 在 App Store Connect 里：Users and Access，Integrations 标签页，App Store Connect API，Team Keys，然后点 Generate API Key。需要 Admin 账号，[Expo 的指南](https://github.com/expo/fyi/blob/main/creating-asc-api-key.md) 给密钥分配的也是 Admin 角色。

第二种情况下，记下有效密钥列表中显示的 Key ID，以及 [Integrations 页面顶部](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests) 的 Issuer ID。最重要的是保管好 `.p8` 文件：[它只能下载一次](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)，Apple 不会保留副本。

> 根据 Apple 的说法，Admin 密钥可以创建和删除你账号下的用户。Apple 要求永远不要把密钥放进代码仓库。

## 可直接复制的最简 eas.json

所有值都是假的：换成你自己的。

```json
{
  "cli": {
    "appVersionSource": "remote"
  },
  "build": {
    "production": {
      "autoIncrement": true
    }
  },
  "submit": {
    "production": {
      "ios": {
        "ascAppId": "1234567890",
        "appleTeamId": "ABCDE12345",
        "ascApiKeyPath": "./keys/AuthKey_XXXXXXXXXX.p8",
        "ascApiKeyIssuerId": "your-issuer-id",
        "ascApiKeyId": "XXXXXXXXXX"
      }
    }
  }
}
```

- **`appVersionSource` 和 `autoIncrement`**：由 EAS 服务器保存构建号，每次生产构建自动加一。从 EAS CLI 12 起，[Expo 推荐这种远程模式](https://docs.expo.dev/build-reference/app-versions/)。
- **`ascAppId`**：你的应用记录编号。没有它，非交互模式会失败。
- **`appleTeamId`**：你的 Apple Developer 团队 ID。
- **`ascApiKeyPath`、`ascApiKeyIssuerId`、`ascApiKeyId`**：你的 API 密钥。这三个字段都支持环境变量。记得把 `keys` 文件夹加进 `.gitignore`。

`appleId` 字段只在你用 Apple ID 登录时才需要。如果 EAS 已经在管理你的密钥，也把三个 `ascApiKey` 字段删掉。我在 10 月 25 日核对了自己的三个应用，生产提交配置里只有 `ascAppId`，Solys 多一个 `appleTeamId`：文件里没有任何密钥。

## 先构建，再上传

```bash
eas build --platform ios --profile production
eas submit --platform ios
```

不加其他参数时，`eas submit` 会让你选择要上传的构建，第一次运行还会问你的 Apple ID。如果存在 `production` 提交配置，就默认使用它。[EAS CLI 参考](https://docs.expo.dev/eas/cli/) 列出了可以跳过选择的参数：

| 参数             | 作用                |
| ---------------- | ------------------- |
| `--latest`       | 上传最新的 iOS 构建 |
| `--id`           | 上传指定的 EAS 构建 |
| `--path`         | 上传本地 .ipa 文件  |
| `--url`          | 上传在线归档文件    |
| `--groups`       | 加入内部测试组      |
| `--what-to-test` | 填写“What to test”  |

想一步到位，就在构建命令后加上 `--auto-submit`。根据 [Expo 关于自动提交的页面](https://docs.expo.dev/build/automate-submissions/)，构建完成后会用与构建配置同名的提交配置交给 EAS Submit。要换一个配置：`--auto-submit-with-profile=name`。**构建会进入 TestFlight，而不是进入审核。**

在持续集成中，加上 `--non-interactive` 和 `EXPO_TOKEN` 令牌。此时命令无法向你提问：配置里必须有 `ascAppId`，还要有 API 密钥，可以是 EAS 关联到应用的那把，也可以是你填在三个 `ascApiKey` 字段里的那把。

## 上传之后会发生什么

**1. Apple 处理构建。** 构建必须先经过处理才会出现在 App Store Connect 里，处理完后 [Apple 会给你发邮件](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds)。Expo 的说法是，一般要 10 到 15 分钟才能在 TestFlight 看到。

**2. 出口合规。** Missing Compliance 状态表示你还没声明加密情况。每个新版本 App Store Connect 都会问这些问题，除非 Info.plist 已经给出答案。在 Expo 中，对应的键是 `ios.config.usesNonExemptEncryption`：

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

根据 [Apple](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations)，如果你的应用（包括所用的库）不使用任何加密，或只使用豁免的加密，就可以填 `false`。系统自带的加密，比如通过 URLSession 使用 HTTPS，通常属于豁免范围。**只有对你的应用确实成立时才声明 `false`：这份声明是要你负责的。** 和 Info.plist 里的任何键一样，修改后需要重新构建。

**3. TestFlight。** 到了 Ready to Submit 状态，[按照 Apple 的说明](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses)，构建可以发给内部测试员，可以提交 Beta 审核给外部测试员，也可以提交 App Store 审核。配置里的 `groups` 字段会把它加入你的内部测试组。其余内容见 [用 TestFlight 测试你的应用](https://devoria.fr/zh-hans/blog/testflight-guide-test-iphone-app)。

## 上传不等于提交审核

[Expo 写得很明白](https://docs.expo.dev/submit/introduction/)：TestFlight 构建不会自动发布到 App Store。EAS Submit 不会替你填写应用信息，也不会上传截图。在 App Store Connect 里还剩四步，详见 [Apple 关于提交审核的帮助文档](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/submit-an-app)：

1. **填写该版本的必填元数据。**
2. **在版本的 Build 部分选择构建。**
3. **点击“Add for Review”。** 版本变成 Ready for Review，但此时还没有真正进入审核。
4. **点击“Submit for Review”。** 审核开始后，状态会变成 In Review。

## 常见错误及解决办法

| 显示的错误          | 原因                 | 解决办法                  |
| ------------------- | -------------------- | ------------------------- |
| ITMS-90189          | 构建号已被使用       | `autoIncrement`           |
| ITMS-90062 或 90186 | 版本已关闭           | 提高 `version`            |
| “Set ascAppId”      | CI 中缺少 `ascAppId` | 添加 `ascAppId`           |
| “API Keys cannot”   | 没有关联密钥         | `eas credentials`         |
| ITMS-90683          | 缺少权限说明文字     | `ios.infoPlist`           |
| ITMS-91053          | 隐私清单不完整       | `ios.privacyManifests`    |
| ITMS-90725          | iOS SDK 太旧         | 升级 Expo SDK             |
| Missing Compliance  | 未声明加密           | `usesNonExemptEncryption` |

据 Expo 说，构建号重复是上传被拒的常见原因：详见 构建号与版本号。有三个错误有单独的指南：[Expo 中的 ITMS-90683](https://devoria.fr/zh-hans/blog/itms-90683-missing-purpose-string-expo)、[Expo 中的 ITMS-91053](https://devoria.fr/zh-hans/blog/itms-91053-missing-api-declaration-expo) 和 ITMS-90725。

两条带引号的消息来自 EAS，在 EAS 配置里就能解决。Missing Compliance 也可以通过在 App Store Connect 里回答问题来解决。**其余各行的修复都涉及二进制文件：重新构建，然后重新上传。** 远程更新改不了 Info.plist、隐私清单，也改不了版本号和构建号。

## 第一次上传应用，少走弯路

这条命令只是其中一步。[iOS Kit](https://devoria.fr/zh-hans/kits/ios) 以我自己应用的 Starter Code 为基础，包含订阅功能，分四个步骤带你一直走到 App Store，节奏由你掌握。

如果你在准备第一次上架，[来做免费诊断](https://devoria.fr/zh-hans/diagnostic)：它会告诉你真正卡住你的是什么，并把我的 Apple 防拒审清单发给你。应用信息、截图和审核通过，[在 App Store 上发布应用](https://devoria.fr/zh-hans/expertise/publish-an-app-on-the-app-store) 页面涵盖了每一步。

## 常见问题

### 如何把 Expo 应用发布到 App Store？

用 EAS Build 生成生产构建，再用 `eas submit --platform ios` 上传。Apple 处理完后，它会出现在 TestFlight 里。然后在 App Store Connect 里填写应用信息，在版本中选择这个构建，再依次点击“Add for Review”和“Submit for Review”。

### EAS Submit 会把我的应用提交给 Apple 审核吗？

不会。EAS Submit 只把二进制文件上传到 App Store Connect，构建进入 TestFlight。提交审核需要在 App Store Connect 里手动完成，前提是应用信息已填好、构建已选定。

### 在哪里找到应用的 ascAppId？

在 App Store Connect 里打开你的应用，进入 App Information，General Information 下的 Apple ID 字段就是。它是一串数字，不要和 Bundle ID 搞混。

### 使用 eas submit 需要 Apple ID 吗？

第一次运行时，命令会向你要 Apple ID。之后，只要配置里有 `ascAppId` 和一把 App Store Connect API 密钥，它就能无需交互地运行，在持续集成中也一样。API 密钥是 Expo 默认且推荐的方式。

### 多久能在 TestFlight 里看到构建？

Expo 的说法是，Apple 处理一般需要 10 到 15 分钟，完成后会给你发邮件。如果构建停在 Missing Compliance 状态，就回答关于加密的问题，然后在配置里声明，以便后续构建使用。


## 你的项目

[Apple Review Kit](https://devoria.fr/zh-hans/kits/review-apple)：我在用的 App Store 审核检查清单、我被 Apple 拒绝后的修改、给审核员的备注，以及两个审查你 App 的 Claude Code skills。29 €。

[iOS Kit](https://devoria.fr/zh-hans/kits/ios)：用 Claude Code 做你的 iPhone App：我自己 App 的起步代码、检查其工作的 skills，以及 Apple Review Kit、App Store Screenshots Kit 和 ASO Kit。129,99 €。
