肇鑫的技术博客

业精于勤,荒于嬉

iOS app与watchOS app数据同步

保存的数据库采用realm。手表部分的app具备与iOS端相同的功能。

基础部分

数据保存在用户的Document里。升级app数据不会消失,卸载app数据会消失。

同步算法

以iOS端为核心。watchOS发起同步请求。

首次启动

WCSession的生命周期最为标准。每次WCSessionDelegatesession(_:activationDidCompleteWith:error:)的运行被认为是一次首次启动。

  • iOS:设定需要同步数据库needSyncDatabase = true。在同步数据库完成之前,不会发送新的同步信息。
// MARK: - WatchConnectivity
extension AppDelegate:WCSessionDelegate {
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        if transfer?.isTransferring == true { transfer?.cancel() }
        
        needSyncDatabase = true
        transfer = session.transferUserInfo(["needSyncDatabase":needSyncDatabase])
    }
    
    func sessionDidBecomeInactive(_ session: WCSession) {
        
    }
    
    func sessionDidDeactivate(_ session: WCSession) {
        
    }
}
  • watchOS:设定同步数据库,手表端有两种情况。
    • WCSession首次启动时主动同步。
    • 接收到iOS发来的同步请求时同步。
// MARK: -WCSessionDelegate
extension ExtensionDelegate:WCSessionDelegate {
    func shouldSyncDatabase() -> Bool {
        return needSyncDatabase && !isSyncingDatabase
    }
    
    func willSyncDatabase() {
        isSyncingDatabase = true
    }
    
    func didSyncDatabase() {
        needSyncDatabase = false
        isSyncingDatabase = false
    }
    
    func syncDatabase() {
        guard shouldSyncDatabase() else { return }
        willSyncDatabase()
        // sync database
        didSyncDatabase()
    }
    
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        syncDatabase()
    }
    
    func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
        if let value = userInfo["needSyncDatabase"] as? Bool {
            needSyncDatabase = value
            syncDatabase()
        }
    }
}

运行中

  • iOS
    • 当数据库改变时,发送需要同步的数据。
    • 接收需要同步的数据,存入数据库。

思路

iOS -> watchOS 同步