From 40768a80d7576b24a786effc2e8964e3dc8ca128 Mon Sep 17 00:00:00 2001 From: GRJeon <104538652+GRJeon@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:14:20 +0900 Subject: [PATCH 1/2] fix: watch state push retry --- .../AppleWatch/WatchConnectionManger+watchOS.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift b/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift index cec04f06..b4da93fc 100644 --- a/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift +++ b/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift @@ -102,7 +102,7 @@ final class WatchConnectionManager: NSObject { } /// iPhone에게 Watch 앱 상태를 전달합니다. - private func pushWatchAppState(_ state: AppStateValue) { + private func pushWatchAppState(_ state: AppStateValue, retryCount: Int = 0) { guard let session = self.session else { self.logger.error("WCSession이 지원되지 않아 상태를 푸시할 수 없습니다.") return @@ -112,7 +112,16 @@ final class WatchConnectionManager: NSObject { try session.updateApplicationContext([MessageKey.appState.rawValue: state.rawValue]) self.logger.info("Watch 앱 상태 푸시: \(state.rawValue)") } catch { - self.logger.error("Watch 앱 상태 푸시 실패: \(error.localizedDescription)") + self.logger.error("실패: \(error.localizedDescription) (시도: \(retryCount + 1))") + // 최대 3번까지만 재시도 + if retryCount < 3 { + let nextRetry = retryCount + 1 + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in + self?.pushWatchAppState(state, retryCount: nextRetry) + } + } else { + self.logger.error("최대 재시도 횟수 초과. 포기합니다.") + } } } From 458c931173c60d93d80f50bcaf53c3a9d85e6d87 Mon Sep 17 00:00:00 2001 From: GRJeon <104538652+GRJeon@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:18:54 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=83=81=ED=83=9C=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=20=EC=9A=94=EC=B2=AD=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Browser/WatchConnectionManager+iOS.swift | 7 +++++++ .../WatchConnectionManger+watchOS.swift | 21 +++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mirroringBooth/mirroringBooth/Device/Camera/Browser/WatchConnectionManager+iOS.swift b/mirroringBooth/mirroringBooth/Device/Camera/Browser/WatchConnectionManager+iOS.swift index d4b2b45e..d1a665c5 100644 --- a/mirroringBooth/mirroringBooth/Device/Camera/Browser/WatchConnectionManager+iOS.swift +++ b/mirroringBooth/mirroringBooth/Device/Camera/Browser/WatchConnectionManager+iOS.swift @@ -12,6 +12,7 @@ import WatchConnectivity final class WatchConnectionManager: NSObject { private enum ActionValue: String { + case pushState case capture case connect case prepare @@ -198,6 +199,12 @@ extension WatchConnectionManager: WCSessionDelegate { if let error: Error = error { self.logger.error("WCSession 활성화 실패: 오류=\(error.localizedDescription)") } else { + session.sendMessage( + [MessageKey.action.rawValue: ActionValue.pushState.rawValue], + replyHandler: nil + ) { error in + self.logger.warning("WCSession handshake 실패: \(error)") + } self.logger.info("WCSession 활성화 성공") } } diff --git a/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift b/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift index b4da93fc..8b41b65a 100644 --- a/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift +++ b/mirroringBooth/mirroringBooth/Device/Remote/AppleWatch/WatchConnectionManger+watchOS.swift @@ -12,6 +12,7 @@ import WatchConnectivity final class WatchConnectionManager: NSObject { private enum ActionValue: String { + case pushState case capture case connect case prepare @@ -36,6 +37,7 @@ final class WatchConnectionManager: NSObject { private let session: WCSession? private let logger = Logger.watchConnectionManager private var lastAppState: AppStateValue = .terminated + private var watchState: AppStateValue = .inactive var onReachableChanged: ((Bool) -> Void)? @@ -102,7 +104,7 @@ final class WatchConnectionManager: NSObject { } /// iPhone에게 Watch 앱 상태를 전달합니다. - private func pushWatchAppState(_ state: AppStateValue, retryCount: Int = 0) { + private func pushWatchAppState(_ state: AppStateValue) { guard let session = self.session else { self.logger.error("WCSession이 지원되지 않아 상태를 푸시할 수 없습니다.") return @@ -112,16 +114,8 @@ final class WatchConnectionManager: NSObject { try session.updateApplicationContext([MessageKey.appState.rawValue: state.rawValue]) self.logger.info("Watch 앱 상태 푸시: \(state.rawValue)") } catch { - self.logger.error("실패: \(error.localizedDescription) (시도: \(retryCount + 1))") - // 최대 3번까지만 재시도 - if retryCount < 3 { - let nextRetry = retryCount + 1 - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in - self?.pushWatchAppState(state, retryCount: nextRetry) - } - } else { - self.logger.error("최대 재시도 횟수 초과. 포기합니다.") - } + self.logger.error("실패: \(error.localizedDescription)") + self.watchState = state } } @@ -245,6 +239,11 @@ extension WatchConnectionManager: WCSessionDelegate { Task { @MainActor in self.onReceiveCaptureComplete?() } + } else if actionValue == ActionValue.pushState.rawValue { + self.logger.info("상태 푸시 명령 수신됨.") + Task { @MainActor in + self.pushWatchAppState(watchState) + } } }