如果您开发的 app 没有上架 app store,那么您肯定会考虑如何保证用户及时收到 app 更新的问题,如果您的项目是开源在某个托管平台的,那么本文就提供一种简单的方式助您实现 app 检查更新的功能。
实现平台
- macOS 10.14.3
- swift 4.2.1
- xcode 10.1
1. 思路
本文提供的方法,不需要架设服务器,只要在开源平台上托管就可以。所以,这里假设您的 app 都是在托管平台发布,并且代码也是及时推送到托管平台的。
每个 xcode 工程中都有一个 info.plist
文件,使用其中的 CFBundleShortVersionString
键的值作为版本判断依据,app 运行起来本身能获取自己的版本号,通过网络从托管平台获取最新版本源文件中的 info.plist
文件,然后得到最新版本号,与自身的版本号对比,如果不一样就说明有了最新版本(更严格的判断应该是远端文件中获取的版本号新于 app 自身的版本号),然后通过提示框提醒用户有新版本发现,提示框中给出一个按钮,帮助用户跳转到开源工程最新版本的 release 页面即可。
注:本文描述的具体方法不适用于Xcode 11及以上版本,因为 info.plist 的内容有变化,不过可以继续使用此文描述的思路,不同的是需要解析的文件不是info.plist
而是xxxxx.xcodeproj/project.pbxproj
,版本就是其中的MARKETING_VERSION
。
这里以工程托管在 github 为例,说明几点注意的地方:
- 请求的
info.plist
文件链接必须是直接指向原文件的,而不是浏览代码页面对应的链接,网页 github 平台上浏览工程代码,找到info.plist
文件,然后点击如图位置的raw
按钮即可得到源文件的直链:
- 跳转最新 release 的页面是根据 tag 名进行跳转的,所以 tag 名称最好与版本号命名规则一致,当然不一致也可以,只要最终能对应上就可以,比如十里的一个开源项目 textGO,对应 tag 的 release 页面链接可以轻易获得:
https://github.com/smslit/textGO/releases/tag/v0.3
,规则就是https://github.com/smslit/textGO/releases/tag/v
+ 版本号 - 第一步网络请求
info.plist
文件使用 GET 请求即可完成,网络请求相关内容可以通过另一篇文章了解:macOS 开发之实现 HTTP 的 GET 和 POST 请求
2. 示例
下面以十里的开源项目 textGO 为例说明一下实现。
2.1 更新器类
因为十里将项目托管到的是 github 平台,所以封装的更新器类仅适用于 github,如果适配其它平台只需修改两处 url 的处理即可。更新器类为 TextGoUpdater ,在文件 TextGoUpdater.swift
中定义,您可以打开这个文件查看具体实现代码。
2.1.1 属性
TextGoUpdater 类中定义了两个属性,分别是 user
、url
。
-
user
指的是 github 的账户名 -
url
指的是info.plist
文件的直链
2.1.2 方法
-
init(user:)
初始化方法,初始化过程中根据提供的 github 账户名和工程名推断出info.plist
文件的直链并赋给 url 属性 -
check(callback:)
触发检查更新的过程,是公共方法。callback
是个逃逸闭包,完成网络请求后在进行数据处理前执行,主要方便调整控件的状态。 -
checkUpdateRequestSuccess(data:response:error:callback:)
封装了网络请求完成后的处理过程,是私有方法。另外使用的两个tipInfo
方法在TextGoPublic.swift
文件中定义,用来显示提示框告知用户检测更新的结果。检测到更新以后,会根据类的 user 属性和工程名称以及最新版本号推断出 release 页面链接。
2.1.3 使用方法
使用方法很简单,主要分两种:有回调和没有回调。
2.1.3.1 无回调使用
可以在文件 AppDelegate.swift
中看到使用方法
- 定义属性 updater
let updater = TextGoUpdater(user: "smslit") {}
- 在
checkUpdate()
方法中直接调用 updater 实例的 check 方法:
@objc func checkUpdate() {
updater.check() {}
}
2.1.3.2 有回调使用
- 定义属性 updater
let updater = TextGoUpdater(user: "smslit") {}
- 在
checkUpdate()
方法中直接调用 updater 实例的 check 方法:
@objc func checkUpdate() {
updater.check() {
// 实现对界面控件的调整
}
}
3. 执行效果
textGO 是一个菜单栏小工具,通过点击检查更新
菜单项触发更新的检查,为了更好的展示效果,以视频展示,同时修改版本号来查看有更新和没更新两种情况的效果。