一个人在深圳,把App送上App Store的血泪全流程

API打磨师
2026-01-04 23:18
阅读 680

上周五凌晨两点,我盯着Xcode里那个绿色的“Upload succeeded”提示,差点哭出来。不是感动,是终于不用再被产品经理@了。

作为一个在深圳远程办公的独立开发者,平时除了写代码、改Bug、参加线上技术分享会,最大的社交活动可能就是和App Store审核团队“斗智斗勇”。没有同事可以甩锅,没有运维帮我配证书,连测试都得自己用三台二手iPhone轮着跑——自由是真的自由,孤独也是真的孤独。

这次上架的App,是我业余时间折腾了三个月的Side Project,一个基于SwiftUI的极简笔记工具。本来只想练练手,结果越做越上头,干脆一鼓作气提交审核。没想到这一路踩的坑,比我过去一年在腾讯系公司(虽然没进去,但深圳这地方,谁还没面过几次?)听到的“对齐颗粒度”还多。

今天就来复盘一下从零到App Store上架的完整流程,重点讲那些文档不会告诉你、但会让你深夜抓狂的细节。顺便聊聊我在优化这个流程时,怎么把“简历项目”变成真正可维护、可交付的产品。


别小看“上架”,它是个系统工程

很多人以为上架就是点个“上传”按钮,其实背后是一整套资源协调 + 工具链配置 + 合规检查的组合拳。尤其当你是一个人干所有活的时候,任何一个环节出问题,都会让你怀疑人生。

我这个项目一开始只是本地跑着玩,后来想上架,才发现:

  • 没有正式的Bundle ID
  • 没配推送证书
  • App图标只画了一个尺寸
  • 隐私描述全是空的
  • 连应用名称都没想好(临时叫“MyNoteBeta”)

这哪是产品,简直是技术债展览馆。


第一步:搞定Apple Developer账户与资源准备

首先,你得有个 Apple Developer Program 会员($99/年)。别想着用免费账号,那只能真机调试,不能上架。

注册完之后,进入 App Store Connect —— 这个界面我熟得能背下来,尤其是每次被拒后刷新审核状态时。

在这里你需要准备的核心资源包括:

  • App Name:不能带“Beta”、“Test”等字样(我第一次就栽在这)
  • Bundle ID:建议用反向域名格式,比如 com.yourname.mynote
  • Privacy Policy URL:必须!现在审核卡得很严,哪怕你的App不收集任何数据,也得有个隐私政策页面(我用GitHub Pages搭了个静态页,5分钟搞定)
  • Screenshots & App Preview:不同设备尺寸都要有,iPhone、iPad分开传
  • Promotional Text & Description:别堆关键词,Apple现在反感ASO作弊

💡 小技巧:截图可以用 Xcode 的 Simulator + QuickTime 录屏,或者直接用 xcrun simctl io booted screenshot screen.png 命令行抓图,效率高还不带状态栏干扰。


第二步:Xcode工程配置——别让证书毁了你

独立开发者最怕的就是 Provisioning Profile 和 Signing Certificate。每次换电脑、重装系统、甚至Apple更新规则,都可能让你的签名失效。

我的做法是:

  1. 在 Xcode 中开启 Automatically manage signing(除非你有特殊需求)
  2. 确保 Bundle ID 和 App Store Connect 里完全一致
  3. Signing & Capabilities 里添加必要功能(如 iCloud、Push Notification),系统会自动申请对应权限

但!如果你用了第三方 SDK(比如 Firebase、AdMob),记得检查它们是否需要额外的 EntitlementsURL Schemes。有一次我集成一个分享库,忘了加 LSApplicationQueriesSchemes,审核直接被拒:“App attempts to access a scheme not declared”。

还有,Build NumberVersion 别搞混:

  • Version 是用户看到的(比如 1.0.0)
  • Build Number 是内部递增的整数(每次上传必须比上次大)

我习惯用脚本自动 bump build number:

#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${INFOPLIST FILE}"

放进 Build Phases 里,每次 Archive 自动+1,再也不用手动改。


第三步:性能与合规:不只是“能跑就行”

Apple 越来越看重 App质量和用户体验。光功能正常不够,还得快、稳、省电。

我这个笔记App虽然是小项目,但我还是做了几项性能优化

  • 使用 @StateObject 而非 @ObservedObject 避免视图重复初始化
  • 图片加载用 AsyncImage(iOS 15+)或封装 URLSession + 缓存
  • 首屏加载时间控制在 400ms 内(用 Xcode Instruments 测过)
  • 所有网络请求走 HTTPS,且 ATS 全开(Info.plist 里别随便关)

另外,隐私清单(Privacy Manifest) 是 iOS 17+ 的新要求。如果你用了任何第三方库(哪怕是 Swift Package),都要检查它是否提供了 PrivacyInfo.xcprivacy 文件。没有?那你得自己补,否则审核不过。

我用的 Markdown 解析库就没提供,只好手动创建并声明:“本组件不收集任何用户数据”。


第四步:Archive 与上传——别在最后一步翻车

一切就绪后,在 Xcode 选择 Generic iOS Device,然后 Product → Archive。

这里有几个坑:

  • 确保 Scheme 是 Release 模式
  • 检查 Bitcode 是否关闭(Apple 已弃用,但有些旧教程还开着)
  • 如果用了 SwiftUI,确保最低部署版本 ≥ iOS 14(否则可能编译失败)

Archive 成功后,打开 Organizer,点击 “Distribute App” → “App Store Connect” → “Upload”。

这时候如果网络不好,可能卡在 99% 半小时。建议挂个代理,或者选个半夜上传(我试过,深圳晚上11点后上传速度明显快)。

上传成功后,回到 App Store Connect,你会看到新构建版本出现在 TestFlightPrepare for Submission 区域。


第五步:填写元数据 & 提交审核

这才是真正的“地狱模式”。

你需要填的信息多到离谱:

类别 内容示例
主要语言 English / 简体中文
支持 URL 邮箱 or 网站
版权信息 © 2024 Your Name
分级问卷 是否含赌博、暴力、用户生成内容等
隐私数据类型 联系方式?位置?标识符?即使没有也要明确声明“None”

最麻烦的是 App Review Information。如果你的App有登录、付费、或者隐藏功能,必须提供测试账号和详细说明。

我这次因为有个“暗色模式切换”藏在设置里,没写说明,第一次审核被拒:“Reviewer cannot find the feature described in metadata.”

第二次我直接在备注里写:

This app has no login, no payment, no backend. All data stored locally. Dark mode toggle is in Settings > Appearance. Please swipe down on the note list to see the floating button.

结果4小时就过了。所以,清晰、诚实、具体,是过审的关键。


工具链推荐:一个人也要有团队效率

作为独立开发者,我攒了一套轻量但高效的工具组合:

  • Fastlane:自动化打包、截图、上传。一条命令搞定 fastlane deliver
  • SwiftLint:保证代码风格统一,提升可读性(毕竟以后可能是别人接手)
  • GitHub Actions:CI 自动跑测试,防止低级错误上主干
  • Notion:管理审核 checklist 和 rejection 历史(别笑,我真建了个数据库)

这些工具不仅提升了交付效率,也让我的项目看起来更“专业”——对,没错,这也是为了简历。毕竟,一个能完整走通 App Store 上架流程的 Side Project,在面试时比十个 TodoMVC 有说服力多了。


审核被拒怎么办?别慌,这是常态

我这次总共提交了3次:

  1. 第一次:App name 含 “Beta” → 拒
  2. 第二次:未说明隐藏功能 → 拒
  3. 第三次:通过 ✅

平均每次等1-2天。Apple 审核员也不是机器人,有时候加一句“Hi, this is a personal project by an indie developer in Shenzhen”反而能加快处理。

被拒不可怕,可怕的是不知道为什么被拒。所以一定要仔细读 Resolution Center 里的每一条反馈。大部分问题其实文档里都有答案,只是我们懒得看。


写在最后:上架不是终点,是起点

当App终于出现在App Store,下载量第一个小时是2(我妈和我自己),说实话有点失落。但转念一想:我一个人,从想法到上线,全流程闭环,还顺手优化了性能、规范了代码、写了文档——这不就是独立开发者的终极浪漫吗?

而且,这套流程跑通一次,下次就快多了。我已经在规划下一个项目,说不定哪天就能 quit 大厂(哦不对,我本来就没进),全职做自己的产品。

如果你也在深圳,一个人敲代码到深夜,不妨试试把你的Side Project送上App Store。过程痛苦,但完成那一刻,你会觉得——值了。

对了,我这个笔记App叫 InkNote,免费无广告,欢迎下载体验(不是打广告,是真的想找用户反馈 😅)。


附:关键Checklist(自用版)

  • Bundle ID 与 App Store Connect 一致
  • Privacy Policy URL 有效
  • 所有设备截图已上传
  • Build Number 递增
  • 隐私清单(Privacy Manifest)齐全
  • 审核备注写清楚隐藏功能/测试路径
  • 关闭调试日志和测试代码

一个人的战争,也要打得漂亮。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝