Files
flutter_server_box/ios/WatchApp/PhoneConnMgr.swift
lollipopkit🏳️‍⚧️ a35d21981b opt.: watch sync mechanism (#817)
* opt.: watch sync mechanism
Fixes #816

* opt.
2025-07-17 16:55:56 +08:00

121 lines
3.5 KiB
Swift

//
// PhoneConnMgr.swift
// WatchEnd Watch App
//
// Created by lolli on 2023/9/16.
//
import WatchConnectivity
class PhoneConnMgr: NSObject, WCSessionDelegate, ObservableObject {
var session: WCSession?
var _ctx: [String: Any] = [:]
var ctx: [String: Any] {
set {
Store.setCtx(newValue)
updateUrls(newValue)
// Notify the view to update, but the [urls] are already published
// so the view will automatically update when [urls] changes.
// DispatchQueue.main.async {
// self.objectWillChange.send()
// }
}
get {
return _ctx
}
}
var userInfo: [String: Any] = [:]
@Published var urls: [String] = []
override init() {
super.init()
if !WCSession.isSupported() {
print("WCSession not supported")
}
session = WCSession.default
session?.delegate = self
session?.activate()
_ctx = Store.getCtx()
updateUrls(_ctx)
}
func updateUrls(_ val: [String: Any]) {
if let urls = val["urls"] as? [String] {
DispatchQueue.main.async {
self.urls = urls.filter { !$0.isEmpty }
}
}
}
func session(
_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState,
error: Error?
) {
// Request latest data when the session is activated
if activationState == .activated {
requestLatestData()
}
}
// Receive realtime msgs
func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
DispatchQueue.main.async {
self.ctx = message
}
}
// Receive UserInfo
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any]) {
DispatchQueue.main.async {
self.ctx = userInfo
}
}
// Receive Application Context
func session(
_ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]
) {
DispatchQueue.main.async {
self.ctx = applicationContext
}
}
private func requestLatestData(timeout: TimeInterval = 5.0, maxRetries: Int = 1) {
guard let session = session, session.isReachable else { return }
var didReceiveResponse = false
var retries = 0
func sendRequest() {
session.sendMessage(["action": "requestData"]) { response in
didReceiveResponse = true
DispatchQueue.main.async {
self.ctx = response
}
} errorHandler: { error in
print("Request data failed: \(error)")
// Optionally, handle error UI here
}
// Timeout handling
DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { [weak self] in
guard let self = self else { return }
if !didReceiveResponse {
if retries < maxRetries {
retries += 1
print("No response, retrying requestLatestData (\(retries))...")
sendRequest()
} else {
print("Request data timed out after \(retries + 1) attempts.")
// Optionally, update UI to indicate timeout
}
}
}
}
sendRequest()
}
}