Files
YuJiWatch/YuJiWatchApp/WatchSessionManager.swift

75 lines
3.0 KiB
Swift

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, Error>) -> 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, Error>) -> 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(()))
}
}
}