Skip to content

App 分发

说明

在本文的最后,有一个标准的 App Store 发版流程,如果希望跳过概念介绍的话可以直接看文末的流程。

在 App 的代码写好后,我们要把它构建成一个可以运行的 App,这叫做 App 的 构建。构建完成后,还需要把它发给用户,这叫做 App 的 分发

理论上你可以直接在 IDE 里点 Build,然后把构建好的安装包直接用 QQ 发给用户。但是由于 苹果是控制狂,不允许你这么干,并且这样的流程也很不规范。这篇文档主要介绍规范的构建和分发流程,解释其中的一些概念,并说明目前旦夕 App 的构建与分发流程中的一些实践。

构建与 CI

CI 的概念和触发方式

构建是把 App 的源代码转换成一个可以运行的 App 的过程(一般也可以被叫做编译)。由于几乎所有代码项目都用 Git 来管理,就有人想出了一个好主意:如果我在某个服务器上弄一个 Xcode,每次检测到 git push 的时候就构建一个版本,那我就能保证代码库始终和构建版本同步,我就再也不需要操心构建了,这不是很好吗?

这确实不错,于是有人给它起名字叫 CI/CD(或者直接叫 CI 也可以)。CI 的基本模式就是在 某个关于代码仓库的事件被触发时,构建一个 App 版本。有以下几种触发方式:

  • push 到仓库
  • 仓库里有一个 PR
  • 打了一个 tag
  • 手动触发

每次 push 到仓库就构建自然是最好的,这会让每一个 commit 都有一个对应的 build,但是这样会消耗很多构建时间,而苹果只给我们免费用有限的构建时间,对于购买额外的构建时间,在座的对于苹果的定价应该不会陌生。所以我们目前使用打 tag 来构建正式版,用手动触发来构建测试版。

App 的版本和构建号

我们都知道一个 App 会有很多版本,如 1.0.0, 1.0.1, 2.1.0 等。除了版本号外,还有一个构建号,一般用递增的数字表示,版本号和构建号连起来一般这样写:2.1.0 (580),代表构建号是 580。

构建号是干什么用的?通常来说在一个版本号内,一个 App 要构建、测试、发现问题打回去重测,循环若干次,最后才能发布。那么每一次构建都会有一个单独的构建号,最终发布给用户的正式版才有版本号,或者说它们都有相同的版本号,但是由不同的构建号区分。

构建号和版本号都在 Xcode 里设置,注意所有的 target,包括 iOS App, watchOS, widget 的版本号和构建号应该保持一致,因此版本更新需要设置 3 次版本号。构建号不用自己设置,CI 会帮你设置好构建号的自动更新。

在 Xcode 中设置 CI

警告

操作前必须在 Xcode 中登录团队的开发者账号

在 Xcode 边栏中点击 Xcode Cloud 板块,可以看到我们设置的几个 Workflow。

  • Build Archive 会构建一个 App,但是不会分发到任何地方
  • Development Build 会构建并发布到开发者账号
  • Internal Release 会发布到内测组
  • External Release 会发布到公测组
  • Production 会检测 GitHub 上的 Tag,一打 Tag 就开始构建,这个最常用,是发布到 App Store 时用的版本

TestFlight 测试

众所周知,iPhone 用户只能从 App Store 下载并安装软件。 众所没那么周知的是,还有一个下载 App 的渠道,叫做 TestFlight。 它的作用是在正式版本发布前,选取一小部分用户让他们使用正在开发的版本,提出反馈并修正后再正式发布,也就是所谓的 beta 版测试。

TestFlight 测试的基本规则

TestFlight 的测试按「组」进行,每个组包含若干个成员,可以将构建版本添加到组里,这样组里的成员就可以下载这个构建版本测试。

组里的成员可以手动指定邮箱,也可以分享一个链接。一般来说链接更方便。

为了防止开发者用 TestFlight 绕过 App Store 审核,苹果做了以下限制:

  • 对于同一个版本的 App,第一次传到 TestFlight 上测试时需要过一遍较宽松的审核,大概要一天左右。后续上传的同一版本不同构建号的 App 免审核。
  • 一个构建版本在 TestFlight 上的有效期是 90 天。90 天后用户即使已经安装到手机也无法继续使用这个版本,必须去更新。
  • TestFlight 总的用户量不得超过 10000 人,但是这个限制对我们没什么用。

旦夕 App 的实践

目前也没有建立起比较规范的 TestFlight 管理制度,可能也没有必要建立,我们毕竟是小团队,灵活优先。但是它主要有以下几种场景:

  • 团队内测。在发布前先让团队内的同学测试一下。这个有专门的测试组。
  • 用户内测。这个也有测试组。这个组偶尔也在出现影响较大的 bug,但被 App Store 卡审核时临时发布修复版本用。
  • 专门的功能内测,如创意银行,这个一般是临时建一个测试组。
  • bug 信息收集。由于我们是非官方的校园服务 App,在用户那里出现数据解析问题时我们无法问学校要后台数据,因此只能在用户手机上记录一些 log 并让用户导出给我们。这时候就要构建一个专门的 App,带有记录和导出功能。这个 App 可以通过 TestFlight 发给用户。

App Store 分发

App Store 分发是最后一步。

警告

App Store 新版发布后,不能再往 App Store 传任何同样版本号的 App。例如 2.1.0 (354) 发布后,向 App Store 提交 2.1.0 (356) 会被直接拒绝。即使你只是想在 TestFlight 发布而不提审也不行。只能发 2.1.1 或者更新的版本。

备案!都给我备案!

为了维护我们国家网络环境的安全与清朗,现在每个手机 App 都要备案并且要有备案号。我们也有自己的备案号,但是我们备案号里 App 的名字叫「校园助手」,而 App Store 里叫旦挞。

苹果在你提交审核时会用机器检查你的 App 名字和备案号是否一致。如果不一致,就会禁止你提审。但是这是纯机器的检查,并且它有一些 bug,可以很容易地绕过:

  1. 在 App 信息里编辑 App 名字,改成「校园助手」。
  2. 提审,如果仍然禁止提审,这是因为发布者名字和备案也不符,但是这个时候只要去 App 信息页里,点那个红色警告栏中的「确认信息」按钮就行了。
  3. 提审,然后把 App 名字改回来。

一个建议的标准化发版流程

由于我们只有 App Store 一个发布渠道,这个流程相对比较简单。

  1. 在仓库里打 tag 并 push,等待 CI 构建新版本。
  2. 写更新日志,并在 App Store 里各个平台处提交审核。
  3. 在仓库里把版本号改成下一个版本(记得三个平台都要改),commit 并 push,并运行一下 Internal Release CI,把新版的 TestFlight 审核先搞上,以便当我们需要临时 TestFlight 发布时不需要再等待审核。