import Foundation import WatchConnectivity import WidgetKit /// 手表端会话管理:激活 WCSession、传录音文件到 iPhone、维护今日速记数并刷新复杂功能。 @MainActor final class WatchSessionManager: NSObject, ObservableObject, WCSessionDelegate { static let todayCountKey = "yujiTodayCount" static let todayDateKey = "yujiTodayDate" @Published var transferState = "" @Published var todayCount = 0 private var completions: [String: (Result) -> Void] = [:] override init() { super.init() todayCount = Self.loadTodayCount() if WCSession.isSupported() { let session = WCSession.default session.delegate = self session.activate() } } /// 今日速记数:按自然日归零,存在手表本地 UserDefaults static func loadTodayCount() -> Int { let defaults = UserDefaults.standard let today = Calendar.current.startOfDay(for: Date()) if let saved = defaults.object(forKey: todayDateKey) as? Date, Calendar.current.isDate(saved, inSameDayAs: today) { return defaults.integer(forKey: todayCountKey) } defaults.set(today, forKey: todayDateKey) defaults.set(0, forKey: todayCountKey) return 0 } private func bumpTodayCount() { todayCount = Self.loadTodayCount() + 1 UserDefaults.standard.set(todayCount, forKey: todayCountKey) WidgetCenter.shared.reloadAllTimelines() } /// 传录音文件到 iPhone,完成后回调(成功时今日数 +1 并刷新复杂功能) func transfer(url: URL, completion: @escaping (Result) -> Void) { guard WCSession.isSupported(), WCSession.default.activationState == .activated else { completion(.failure(NSError(domain: "YuJiWatch", code: 1, userInfo: [NSLocalizedDescriptionKey: "手表与 iPhone 未连接,录音先存在手表上,连上后会自动重传。"]))) return } let transfer = WCSession.default.transferFile(url, metadata: ["createdAt": Date().timeIntervalSince1970]) completions[transfer.file.fileURL.lastPathComponent] = completion transferState = "正在传到 iPhone…" } // MARK: - WCSessionDelegate func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { // 激活完成即可传文件,无需额外处理 } func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) { let key = fileTransfer.file.fileURL.lastPathComponent guard let completion = completions.removeValue(forKey: key) else { return } if let error { transferState = "传输失败:\(error.localizedDescription)" completion(.failure(error)) } else { transferState = "已传到 iPhone" bumpTodayCount() completion(.success(())) } } }