Live Activity (위젯) 트러블슈팅
·5 min read
문제 상황
- 일시정지해도 위젯 타이머가 계속 실행됨
- 자동 일시정지 시 앱은 5초인데 위젯은 4초로 표시
- 위젯 일시정지 버튼 눌러도 앱에서 아무 변화 없음
- 러닝 중과 일시정지 시 타이머 폰트가 다름
- 위젯에 로고 이미지가 표시되지 않음
- 여러 번 pause/resume 시 시간 누적 오류
- 백그라운드에서 첫 auto-pause 후 이후 auto-pause가 작동하지 않음
원인 분석
-
일시정지 타이머 계속 실행:
LiveActivityManager.update()에서isPaused=true여도startTimeInMilliseconds를nil로 설정하지 않아 위젯이 타이머를 계속 구동 -
자동 일시정지 시간 불일치: JS 스톱워치 시간과 Native에서 계산하는 시간이 별도로 관리되어 미세한 차이 발생
-
위젯 버튼 작동 안 함: 딥링크 처리에서
isRunningRef.current조건이 실제workoutState와 불일치 -
폰트 불일치: 러닝 중
Text(timerInterval:)에는.monospacedDigit()적용, 일시정지Text(duration)에는 미적용 -
이미지 안 보임:
Image(imageName)직접 사용 시 위젯 확장에서 Asset 접근 불가 -
시간 누적 오류:
pauseStartDate초기화 누락으로 일시정지 시간이 잘못 계산됨 -
백그라운드 auto-pause 실패: JS 타이머(
setTimeout)는 앱이 백그라운드로 가면 suspend됨. 첫 번째 auto-pause는 앱이 포그라운드일 때 작동하지만, 이후 앱이 백그라운드 상태에서는 JS 코드가 실행되지 않아 auto-pause 로직이 동작하지 않음
해결 과정
-
LiveActivityManager.update() 수정:
isPaused=true일 때startTimeInMilliseconds = nil설정- 위젯이 타이머 대신 고정된
duration문자열 표시
-
JS-Native 시간 동기화:
WorkoutSessionManager.pauseWorkout(elapsedTimeMs)파라미터 추가- 브릿지 파일(
WorkoutSessionManager.m) 수정 - JS에서 정확한 경과 시간을 Native로 전달
-
딥링크 처리 개선:
isRunningRef.current조건 제거workoutState만으로 판단하도록 변경- 딥링크 URL 형식 통일 (
action=pause,action=resume)
-
폰트 일관성 적용:
- 모든 타이머 Text에
.monospacedDigit()추가 LiveActivityView.swift,LiveActivityWidget.swift수정
- 모든 타이머 Text에
-
이미지 로딩 수정:
resizableImage(imageName:)헬퍼 함수 사용Image.dynamic()통해 Asset과 파일 경로 모두 지원
-
일시정지 시간 추적 변수 추가:
totalPausedDuration: 누적 일시정지 시간pauseStartDate: 현재 일시정지 시작 시점- resume 시 정확히 초기화
-
Native Auto-Pause 구현:
- 문제: JS 기반 auto-pause는 앱이 백그라운드일 때 작동하지 않음 (JS 타이머 suspend)
- 해결: GPS 위치 업데이트를 받는
LocationTracker.swift에서 직접 auto-pause 처리 checkAutoPause(currentSpeed:): 속도 0.3 m/s 미만이면 5초 후 자동 일시정지triggerAutoPause(): Live Activity 즉시 업데이트 + JS에 이벤트 전송triggerAutoResume(): 속도 감지 시 3초 후 자동 재개- JS에서는
autoPauseStateChanged이벤트를 수신하여 상태 동기화
배운 점 및 회고
- SwiftUI Text(timerInterval:):
startTimeInMilliseconds가 설정되면 위젯이 자동으로 타이머 구동. 일시정지 시 반드시nil로 설정 필요 - JS-Native 동기화: 시간처럼 정확도가 중요한 값은 한쪽에서 계산하여 전달하는 것이 안전
- 딥링크 상태 체크: 여러 상태 변수를 AND 조건으로 체크하면 동기화 문제 발생 가능. 하나의 신뢰할 수 있는 상태로 판단
- 위젯 확장 제약: 위젯 확장은 메인 앱과 별도 프로세스이므로 Asset 접근 시 헬퍼 함수 사용 권장
- 백그라운드 실행: JS 타이머는 앱이 백그라운드로 가면 suspend됨. 백그라운드에서도 작동해야 하는 기능(auto-pause 등)은 반드시 Native에서 처리