Firebase Remote Config 建立強制/建議更新機制
- Firebase 設定
- 判斷更新類型
- 建立 AppUpdateManager 處理 remote config 更新邏輯
- 即時監聽更新
1. Firebase 設定
前往 Firebase 後台設定 Remote Config
- key:
update_version
- value(JSON 格式):
{ "force_update_version": "設定的強制更新版本號", "recommend_update_version": "設定的建議更新版本號" }

建立一個 struct 存取資料
struct UpdateResponse: Codable {
let forceUpdateVersion, recommendUpdateVersion: String
enum CodingKeys: String, CodingKey {
case forceUpdateVersion = "force_update_version"
case recommendUpdateVersion = "recommend_update_version"
}
}
2. 判斷更新類型
宣告一個 enum 用來定義更新的類型
compareVersions
用來比較兩個數字的字串
checkForUpdates
主要邏輯,判斷要回傳什麼 UpdateType
enum UpdateType {
/// 不更新
case none
/// 建議更新
case recommend
/// 強制更新
case force
static func checkForUpdates(currentVersion: String, forceUpdateVersion: String, recommendUpdateVersion: String) -> UpdateType {
let currentVersionComparison = compareVersions(currentVersion, forceUpdateVersion)
let recommendUpdateComparison = compareVersions(currentVersion, recommendUpdateVersion)
if currentVersionComparison == .orderedSame && recommendUpdateComparison == .orderedAscending {
return .recommend
} else if currentVersionComparison == .orderedAscending || recommendUpdateComparison == .orderedAscending {
return .force
} else {
return .none
}
}
private static func compareVersions(_ version1: String, _ version2: String) -> ComparisonResult {
return version1.compare(version2, options: .numeric)
}
}
3. 建立 AppUpdateManager 以處理 remote config 的更新邏輯
定義一個 protocol 讓其他類別處理各種更新類型邏輯
protocol UpdateTypeHandler {
func handleUpdate(type: UpdateType)
}
建立 AppUpdateManager,讓外部注入 RemoteConfig
updateVersion
remote config 設定的 key
currentVersion
目前 App 版號
class AppUpdateManager {
let updateVersion = "update_version"
private var currentVersion: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
}
private let remoteConfig: RemoteConfig
init(remoteConfig: RemoteConfig) {
self.remoteConfig = remoteConfig
}
private var updateTypeHandler: UpdateTypeHandler?
func registerUpdateTypeHandler(handler: UpdateTypeHandler) {
self.updateTypeHandler = handler
}
}
將 remote config 的 JSON 轉換成 model,並取得更新類型
private func getUpdateType() -> UpdateType {
let jsonData = remoteConfig[updateVersion].dataValue
guard let updateResponse = UpdateResponse.decode(from: jsonData) else {
return .none
}
let forceUpdateVersion = updateResponse.forceUpdateVersion
let recommendUpdateVersion = updateResponse.recommendUpdateVersion
let type = UpdateType.checkForUpdates(currentVersion: currentVersion,
forceUpdateVersion: forceUpdateVersion,
recommendUpdateVersion: recommendUpdateVersion)
return type
}
處理更新的 key
func handleUpdateKey() {
let type = getUpdateType()
self.updateTypeHandler?.handleUpdate(type: type)
}
調用 fetchWithCompletionHandler: 取得在後台設置的所有值
private func checkAppVersion() {
remoteConfig.fetch() { [weak self] (status, error) in
guard let self = self else { return }
guard status == .success, error == nil else {
print("錯誤:\\(error)")
return
}
remoteConfig.activate()
self.handleUpdateType(type)
}
}
建立一個類別 conform UpdateTypeHandler 處理顯示建議、強制更新的邏輯
class AppVersionUpdateHandler: UpdateTypeHandler {
func handleUpdate(type: UpdateType) {
switch type {
case .none:
break
case .recommend:
print("建議更新")
case .force:
print("強制更新")
}
}
}
在以下兩個 App 生命週期呼叫 checkAppVersion
private lazy var appUpdateManager: AppUpdateManager = {
let appUpdateManager = AppUpdateManager(remoteConfig: remoteConfig)
let appVersionUpdateHandler = AppVersionUpdateHandler()
appUpdateManager.registerUpdateTypeHandler(handler: appVersionUpdateHandler)
return appUpdateManager
}()
//第一次開啟 App 時呼叫
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
appUpdateManager.checkAndHandleAppUpdate()
return true
}
//回到 App 前景時呼叫
func applicationWillEnterForeground(_ application: UIApplication) {
appUpdateManager.checkAndHandleAppUpdate()
}
4. 即時監聽更新
Firebase 提供了即時監聽更新機制,調用 addOnConfigUpdateListener
以開始監聽更新並自動提取任何新參數值或更新後的參數值。
不建議做強制、建議更新時做即時監聽更新的機制,會影響使用者體驗
configUpdate.updatedKeys
取得所有更新的 key 值self.appUpdateManager.updateVersion
是一個自定義的常數字串,對應 remote config 所設定的 key
extension AppDelegate {
private func listenForConfigUpdates() {
remoteConfig.addOnConfigUpdateListener { [weak self] configUpdate, error in
guard let self = self else { return }
guard let configUpdate = configUpdate, error == nil else {
print("Error listening for config updates: \\(error)")
return
}
self.remoteConfig.activate { [weak self] changed, error in
guard let self = self else { return }
for updateKey in configUpdate.updatedKeys {
switch updateKey {
case self.appUpdateManager.updateVersion:
self.appUpdateManager.handleUpdateKey()
default:
break
}
}
}
}
}
}
完整程式碼