mcpField
I
ios-app-store-submission

ios-app-store-submission

github.com/kimny1143开发88 次安装
代码仓库

关于 ios-app-store-submission

面向开发 Expo iOS 应用的团队,涵盖本地构建、TestFlight 分发及 App Store 审核提交。内容包括构建准备、环境变量管理、验证与发布前检查。

主要功能

  1. 01Expo 本地预构建与 Xcode 归档流程
  2. 02版本号与构建号检查
  3. 03TestFlight 环境配置
  4. 04App Store Connect 提交步骤
  5. 05发布前诊断与清理

适用场景

  1. 01准备 iOS 应用的 TestFlight 构建
  2. 02提交应用版本进行 App Store 审核
  3. 03排查 TestFlight 中的 API 问题
  4. 04归档前检查发布配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kimny1143/claude-code-template --skill ios-app-store-submission

安装后在 Claude Code 中输入/ios-app-store-submission确认已加载。

详细介绍

iOS 本地构建与提交

完整工作流:本地构建 → 上传至 App Store Connect → 提交 TestFlight 测试 / 应用审核。

基本方针

  • 默认使用本地构建(不使用 EAS Build)
  • EAS Free tier 每月有 30 次构建额度。调试迭代会很快耗尽
  • EAS 基于 git clone → 未纳入 git 的文件不会包含在构建中 → 容易出错
  • 本地构建直接使用文件系统 → 安全、快速、无限制

Phase 0:构建前检查

0.1 确认应用
# どのアプリをビルドするか確認
ls -d */app.json
# → muednote-mobile/app.json, muedear/app.json
0.2 确认分支
用途分支
提交 App Store 审核main
TestFlight 测试feature 分支也可以
git branch --show-current
git status
0.3 确认版本与构建编号
# app.json から現在の version と buildNumber を確認
cat <APP_DIR>/app.json | grep -E '"version"|"buildNumber"'

规则:

  • version:显示在 App Store 上的版本(例如:0.8.4)
  • buildNumber:在同一 version 中必须唯一。始终设为现有最大值 + 1
  • 已在 App Store Connect 中使用过的 buildNumber 不可重复使用
  • version train 关闭后(例如被拒),必须提高 version
0.4 .env 管理

重要:.env 的值是在 xcodebuild archive 时由 Metro bundler 注入,而不是在 prebuild 时注入。

# 現在の .env を確認
cat <APP_DIR>/.env

# バックアップ(初回のみ)
cp <APP_DIR>/.env <APP_DIR>/.env.backup
用途CLERK_KEYAPI_URL
生产环境(App Store)pk_live_...https://mued.jp
测试环境(TestFlight)pk_test_...preview deploy URL

TestFlight 构建时:

# .env を TestFlight 用に変更
# EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
# EXPO_PUBLIC_API_URL=https://<preview-url>.vercel.app

生产环境构建时:

# .env が本番値であることを確認
# EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
# EXPO_PUBLIC_API_URL=https://mued.jp

构建后务必恢复生产环境的值:

cp <APP_DIR>/.env.backup <APP_DIR>/.env

Phase 1:本地构建

1.1 安装依赖项并执行 Prebuild
cd <APP_DIR>
npm install
npx expo prebuild --clean

--clean 会删除并重新生成 ios/。始终添加此参数。

1.2 Archive
xcodebuild -workspace ios/<SCHEME>.xcworkspace \
  -scheme <SCHEME> \
  -configuration Release \
  -archivePath build/<SCHEME>.xcarchive \
  -destination "generic/platform=iOS" \
  DEVELOPMENT_TEAM=F529L4WT3V \
  CODE_SIGN_STYLE=Automatic \
  -allowProvisioningUpdates \
  archive

各应用对应的值:

应用SCHEMEworkspace
MUEDnoteMUEDnoteios/MUEDnote.xcworkspace
MUEDearMUEDearios/MUEDear.xcworkspace
1.3 Export 并上传
xcodebuild -exportArchive \
  -archivePath build/<SCHEME>.xcarchive \
  -exportPath build \
  -exportOptionsPlist ExportOptions.plist \
  -allowProvisioningUpdates

如果没有 -allowProvisioningUpdates,会出现 "No profiles found" 错误。

1.4 ExportOptions.plist

已放置在各应用目录中。如果没有,请创建:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>method</key>
	<string>app-store-connect</string>
	<key>signingStyle</key>
	<string>automatic</string>
	<key>teamID</key>
	<string>F529L4WT3V</string>
	<key>uploadSymbols</key>
	<true/>
	<key>destination</key>
	<string>upload</string>
</dict>
</plist>
1.5 构建后恢复 .env
cp <APP_DIR>/.env.backup <APP_DIR>/.env

Phase 2:操作 App Store Connect

上传完成后,处理将在 5〜15 分钟内完成。

2.1 使用 Chrome 扩展时

可以使用 Claude in Chrome 扩展操作 App Store Connect。

1. tabs_context_mcp で接続確認
2. appstoreconnect.apple.com に navigate
3. ユーザーにログインしてもらう(パスワード入力は禁止)
4. ログイン後、アプリ一覧からスクリーンショットで状態確認

注意:

  • Chrome 扩展连接不稳定。如果断开,请使用 tabs_context_mcp 重新连接
  • 绝对不要输入 Apple ID / 密码,请交由用户处理
  • 执行「提交审核」等不可逆操作前,务必征得用户确认
2.2 发布到 TestFlight(用于测试)
  1. App Store Connect → 应用 → TestFlight 标签页
  2. 确认构建状态为「已完成」(处理完成)
  3. 确认 Internal Testers 群组
  4. 如果已自动添加,即可立即测试
  5. 如果没有,请从「构建」标签页添加构建

出口合规:

  • 如果 app.json 中已设置 ITSAppUsesNonExemptEncryption: false,系统会自动回答
  • 如果未设置,请手动选择「否」
2.3 提交 App Store 审核

⚠ 构建前请清除调试残留:

  • 删除 Settings 屏幕上的 Diagnose 按钮
  • 删除 apiClient.ts 等文件中的调试 console.log
  • 删除临时调试 UI(例如状态横幅)
  • 确认 .env 使用生产环境的值
  1. App Store Connect → 应用 → 分发 标签页
  2. 创建新版本(点击 + 按钮 → 输入版本号)
  3. 确认必填项:
    • 屏幕截图:会从上一版本继承,但有时需要保存
    • 构建:通过「添加构建」选择对应构建
    • 此版本的最新动态:用英文填写更新内容
  4. 保存 → 添加以供审核 → 提交审核

常见错误:

错误处理方法
「请选择构建」构建尚未保存。重新添加并保存
「此版本的最新动态为必填项」填写 What's New
「需要屏幕截图」新版本首次保存后会继承屏幕截图
「版本 X 的 train 已关闭」提高 version(0.8.3 → 0.8.4)

Phase 3:TestFlight 验证(UI 调试)

在 TestFlight 中看不到 console.log。 排查问题时必须在 UI 上显示调试信息。

3.0 实现面向 TestFlight 的调试诊断

在 TestFlight 构建中测试新功能或 API 集成时,务必在 Settings 屏幕上设置 Diagnose 按钮:

// Settings画面に追加
const handleDiagnose = async () => {
  const lines: string[] = [];

  // 1. 認証状態
  lines.push(`Clerk isSignedIn: ${clerkIsSignedIn}`);
  lines.push(`Clerk userId: ${clerkUserId ?? 'null'}`);

  // 2. トークン取得テスト
  try {
    const token = await getToken();
    lines.push(`Token: ${token ? `OK (len=${token.length})` : 'NULL'}`);
  } catch (err: any) {
    lines.push(`Token ERROR: ${err.message}`);
  }

  // 3. API疎通テスト(直接 fetch で生レスポンスを確認)
  try {
    const resp = await fetch(`${BASE_URL}/api/target-endpoint`, { headers });
    const raw = await resp.json();
    // apiSuccess ラップの有無を確認
    lines.push(`API: ${resp.status}`);
    lines.push(`Has data wrapper: ${'data' in raw}`);
    lines.push(`Response keys: ${Object.keys(raw).join(', ')}`);
  } catch (err: any) {
    lines.push(`API ERROR: ${err.message}`);
  }

  Alert.alert('Diagnose', lines.join('\n'));
};

检查要点:

  • 令牌为 NULL → Clerk 会话问题
  • 令牌正常,但 API 返回 401 → 服务端 JWT 验证问题
  • API 返回 200,但数据为 undefined → 响应封装(apiSuccess)未正确解包
  • Has data wrapper: true → 需要在 apiClient.handleResponse 中解包

发布(提交审核)前务必:

  1. 删除 Diagnose 按钮(或将其改为连点触发的隐藏功能)
  2. 删除 apiClient.ts 等文件中的 console.log('[API] Token obtained...') 等调试日志
  3. 删除临时调试 UI 组件(横幅、状态显示等)
  4. 确认以上项目后再构建并提交审核。不要在仍包含调试 UI 的情况下提交审核

Phase 4:构建前验证

4.1 Provider 不要返回 null
grep -r "return null" <APP_DIR>/src/providers/ 2>/dev/null

错误:if (!isLoaded) return null; 正确:返回加载 UI

4.2 ATT 插件配置(仅用于使用广告的应用)
grep -A5 "expo-tracking-transparency" <APP_DIR>/app.json

直接使用字符串 "expo-tracking-transparency" 是错误的。必须使用对象形式。

4.3 检查 gitignore
# modules/*/ios/ が除外されていないか確認
# ios/ ではなく /ios/ (ルート限定) であること
grep "^ios/" <APP_DIR>/.gitignore
grep "^/ios/" <APP_DIR>/.gitignore

ios/ → 排除所有层级中的 ios/(原生模块的 Swift 源文件也会被排除) /ios/ → 仅排除根目录下的 ios/(正确)


各应用快速参考

MUEDnote
cd muednote-mobile
npm install && npx expo prebuild --clean
xcodebuild -workspace ios/MUEDnote.xcworkspace -scheme MUEDnote \
  -configuration Release -archivePath build/MUEDnote.xcarchive \
  -destination "generic/platform=iOS" DEVELOPMENT_TEAM=F529L4WT3V \
  CODE_SIGN_STYLE=Automatic -allowProvisioningUpdates archive
xcodebuild -exportArchive -archivePath build/MUEDnote.xcarchive \
  -exportPath build -exportOptionsPlist ExportOptions.plist -allowProvisioningUpdates
  • Bundle ID:com.mued.note
  • Apple Sign In:有
MUEDear
cd muedear
npm install && npx expo prebuild --clean
xcodebuild -workspace ios/MUEDear.xcworkspace -scheme MUEDear \
  -configuration Release -archivePath build/MUEDear.xcarchive \
  -destination "generic/platform=iOS" DEVELOPMENT_TEAM=F529L4WT3V \
  CODE_SIGN_STYLE=Automatic -allowProvisioningUpdates archive
xcodebuild -exportArchive -archivePath build/MUEDear.xcarchive \
  -exportPath build -exportOptionsPlist ExportOptions.plist -allowProvisioningUpdates
  • Bundle ID:com.mued.muedear
  • AdMob + ATT:有

Gotchas

  • EAS Build は git clone ベース: ローカルにあっても git に入っていないファイルはビルドに含まれない。.gitignore の ios/ が modules/*/ios/ の Swift ソースまで除外していた事故例あり
  • version train がクローズ: App Store Connect でバージョンがリジェクト等でクローズされたら、同じバージョンでは再提出不可。version を上げる
  • buildNumber は使い捨て: 一度使った buildNumber は再利用不可。App Store Connect のビルド一覧で最新番号を確認してからインクリメント
  • .env はビルド後に必ず戻す: TestFlight用の pk_test のまま本番ビルドすると事故る
  • prebuild の --clean は常につける: 古いネイティブコードが残って混乱する原因になる
  • 新バージョンのスクショは一度保存が必要: 新バージョン作成直後はスクショが空に見えるが、保存すると前バージョンから引き継がれる

Common Rejection Reasons & Fixes

1. App Completeness(黒い画面)

Provider が null を返している。ローディング UI を返すように修正。

2. ATT Not Shown

expo-tracking-transparency のプラグイン設定がベア文字列。オブジェクト形式に変更。

3. Accurate Metadata

スクリーンショットが実際のアプリと一致しない。最新版に更新。

4. Sign In Issues

デモアカウント情報がアプリのフォームと一致しない。プレースホルダーが「メールアドレス」ならメール形式で記載。

Resolution Center コメントテンプレート
We have addressed the issue identified in the previous review:

**[Issue] (fixed)**
- Root cause: [Technical explanation]
- Fix: [What was changed]
- File changed: [File path]

Build [N] contains this fix. Thank you for your review.

评论

支持 Markdown