75 lines
3.0 KiB
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(()))
|
|
}
|
|
}
|
|
}
|