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 发布时不需要再等待审核。