구글맵과 CLLocationManager를 이용하여 위치기반 데이터를 수집중이었는데 일반적인 지도앱을 개발중이었는데
백그라운드 상태에서도 경로를 sqlite에 저장해야 하는 상황이었고 앱특성상 5시간 이상 수집을 해야만 했다.
발목을 잡고 태클을 이중 삼중으로 걸었던 부분은 앱 위치정보 사용 설정 부분이었는데 위치정보 사용법은 두가지가 존재한다.
Privacy - Location Always Usage Description (앱을 사용하지 않을때도 위치 수집)
Privacy - Location When In Use Usage Description (앱
도대체 Location Always Usage Description와 Location When In Use Usage Description 중 어떤걸 사용해야 하느냐였다.
찾아보니 Always Usage가 When In Use Usage보다 상위이기에 Always Usage를 쓰면 되고 다만
Always Usage사용시 백그라운드 모드로 이동시 blue status bar가 나타나지 않는다란 설명도 알게 되었다.
하여 아무생각없이 Always Usage 썼고 잘 동작하였다.
그런데 이놈이 3시간만 지나면 무조건 리셋이 되어버리는 상황이 발생한다.
그것도 램 2기가인 아이폰7+에선 12시간이 지나도 잘 돌아가는 반면, 램 고자인 하위 기종에선 최대 아무리 버텨봐야 3시간~4시간이면 100% 앱이 리셋이 되어 앱실행시 지도화면이 아닌 초기화면으로
이동되어 있었다.
질문글을 올려봐도, stackoverflow.com을 검색해 보아도 마땅한 답이 아닌 메모리 관리를 잘해야 한다란 답변들 밖에 들을 수 없었다.
메모리 모니터링을 해봐도 메모리가 누적되진 않았다.
혹시 구글맵의 Camera 이동 코드가 didupdate에 들어가 있어서 백그라운드 모드에서 호출되며 알지 못하는 문제 때문에 앱이 3시간 후 리셋되나? 싶어 그부분도 걷어봤지만 동일할 뿐 나아지지 않았
다.
정말 마지막 시도로 다른 상용 조깅앱인 runkeeper과 비교를 해보았더니 조깅앱은 하루가 지나도 잘만 동작하였다.
외관상 다른점은 딱 하나 blue status bar가 있다란 점.
blue status bar가 나타나게 하려면 Location Always Usage Description이 아닌 Location When In Use Usage Description을 사용하여야만 한다.
하여 기존 Privacy - Location Always Usage Description 대신 Privacy - Location When In Use Usage Description로 바꾸고 테스트를 하였더니 ㅡㅡ
6시간이 지나도 쌩쌩하게 잘만 동작함이 확인 되었다.
[결론]
장시간(3시간 이상)백그라운드 상태에서 계속 위치 정보 수집을 하려들 경우
Privacy - Location When In Use Usage Description / requestWhenInUseAuthorization 사용함과 동시에
iOS9부터 제공하는 setAllowsBackgroundLocationUpdates를 사용하여야만 가능함.
[결론 부가 설명]
애플문서(https://developer.apple.com/reference/corelocation/cllocationmanager/1620551-requestalwaysauthorization)를 보면
"When the user grants “Always” authorization to your app, your app can start any of the available location services while your app is running in the foreground or background."라는 문
구 때문에 마치 requestAlwaysAuthorization을 사용해야만 백그라운드에서 위치 정보 수집이 가능하다 착각하겠지만
애플문서(https://developer.apple.com/reference/corelocation/cllocationmanager/1620562-requestwheninuseauthorization)를 보면
(Apps cannot use any services that automatically relaunch the app, such as region monitoring or the significant location change service.) When started in the foreground, services
continue to run in the background if your app has enabled background location updates in the Capabilities tab of your Xcode project.
즉 "앱이 지역 모니터링이나 중요한 위치 변경 서비스와 같이 앱이 자동으로 서비스를 실행하는건 못하지만 포그라운드에서 실행 후 백그라운드에서 실행 가능하도록 프로젝트를 설정한 경우 백그라
운드에서 계속 실행된다라" 적혀있기 때문에 프로젝트에 백그라운드 지원 설정만 한다면 백그라운드 상태에서도 제한 없이 위치 정보 수집이 가능하다.
오히려 시간 무제한 위치정보를 수집이 가능하다.
이해할 수 없는 점은 애플은 왜 requestAlwaysAuthorization를 만들어 놓고도 OS단에서 3~4시간이 지나면 무조건 리셋을 시켜대는 것일까란 점이다.
[장시간 백그라운드 상태에서 사용자의 위치정보를 수집하는 핵심 방법 정리]
1.프로젝트 설정
프로젝트 > Capabilities > Background Modes > Location update 체크
2.info.plist파일
Privacy - Location When In Use Usage Description 추가 후 적당한 문구 삽입
Privacy - Location Usage Description 추가 후 적당한 문구 삽입
3.소스에서 CLLocationManager 초기화 후 앱사용시에만 위치정보 수집을 하겠다와 백그라운드 상태에서도 위치정보 갱신을 하겠다는 코드 호출
locationManager.pausesLocationUpdatesAutomatically = NO; //자동으로 멈춤 방지
if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[locationManager requestAlwaysAuthorization];
}
if ([locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
[locationManager setAllowsBackgroundLocationUpdates:YES];
}
그러면 이렇게 파랑 상태바가 출몰함