- Coremotion2편- 걷기데이터 & HealthKit2024년 04월 17일
- 2료일
- 작성자
- 2024.04.17.:48
아주아주아주 예전에 작년에!! Coremotion 프레임워크 관련해서 글을 썼었다. 핸드폰 기울기에 따라 공이 움직여 스프라잇킷과 함께 이용하는 거여서 x,y,z, 가속도.. 중력..등등 다양하게 적어놨었다.
오늘은 어쩌다보니 새로운 기획하고 개발하는 앱에는 실시간 걸음수 측정이 필요한데 이를 Healthkit에서는 처리가 어려워서 Coremotion이 적당하여 걸음에 관련된 정리들을 해보려 합니다!!
우선 제가 개발하려는 앱의 목표!
- 유저들의 실시간 걸음에 관한 정보를 얻고 이를 활용해 피드백을 해줍니다.(보폭, 보행속도)등을 미션을 통해 세팅해놓고 달성을 하여 나이드신분들이 더 좋은 걷기 운동을 할수 있게하자!
음...HealthKit이라는 아주 좋은 애플의 건강정보가 있잖아.....그럼 이거써야해?
HealthKit: 사용자의 개인 정보 및 제어를 유지하면서 건강 및 피트니스 데이터의 액세스하고 공유할수 있는 프레임워크
Healthkit은 물론 주는 정보들이 더 많다. 그리고 저장기간도 김..위의 방식대로 요청을 하면 원하는 시점의 데이터도 얻을 수 있다. 하지만 실시간 정보를 얻기엔 힘들다. 여러번 테스트를 해보니까 업데이트 되는데 30-40분이 걸리는거 같다. 그래서 운동 끝나고나서의 피드백통계에는 사용하면 좋겠지만 실시간운동중에 정보들을 제공하려면 Coremotion을 사용해야함!
결국! CoreMotion사용해보자
1. 먼저 생성될때 가능여부를 측정한다.
class CoreMotionService: ObservableObject { init() { guard CMPedometer.isStepCountingAvailable() && CMPedometer.isDistanceAvailable() else {return} }}
2. CoreMotion에서 데이터를 얻어오는 방식은 2가지 방법이 있다.
1. queryPedometerData를 통해 내가 지정해놓은 시간의 데이터를 얻기
2. startupdates를 활용하여 시작시점부터 지속적으로 걸음 데이터갱신하고 handler를 통해 이벤트를 처리한다.
--> 실시간을 걸음수를 업데이트하기에 1의 방식보다 배터리 성능저하, 메모리, CPU과부하가 발생한다.
그래서 1의 방식을 사용하기로 하였다. 우리가 필요한것은 걸을때의 피드백이기에 이 타임을 짧게 타이머를 돌리더라도 위의 방법이 더 적당하다고 생각을 하였다. CMPedometer의 인스턴스를 찍어내고 queryPedometerData라는 메소드를 실행한다. 우리가 지정해놓은 시간들 사이의 데이터들을 가져오는데 기간은 최대 7일전까지 가능하다. 백그라운드에서 정보는 계속 저장되고 그를 가져오는 것!.
data안에는 다양한 프로퍼티들이 있다. currentCadence는 분당 얼마나 걸었는지를 보여주고 currentPace는 가장 마지막에 측정된 속도를 보여준다고 한다. 하지만 나는 기간사이의 평균 속도가 필요하기에 averageActivePace라는 프로퍼티를 사용했다. 유저들에게 자주 피드백을 주기위해 내 앱은 저 기간을 짧게 계속 측정해야한다!
func startSteping() { isCollecting.toggle() pastTime = Date() timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { [weak self] _ in self?.fetchStepData() } } func stopSteping() { isCollecting.toggle() timer = nil }
그래서 10초간격으로 측정을 하며 정보들을 UI를 통해 보여준다.
멈춰있는 상태에는 업데이트가 되지 않도록 어떻게 해줄수 있을까?
좀 더 정확한 데이터값을 주기 위해서는 멈춰있는 것을 감지하고 이때에는 측정을 멈춰야한다.
-> startActivityUpdates method를 사용
그런데 문제가 발생하엿던게 activity에는 멈춤을 인식하는 stationary가 있고 걷기인 walking이외에도 running automotive,cycling이 있는데 다 0으로 뜨는 경우도 있다. 아주 천천히 걸으면 그러는것 같다. 그래서 우리가 원하는 것은 멈춰있는 것만 감지하기위해 stationary일때만 이벤트를 해주고 나머지는 움직이고 있는뜻이기에 타이머를 통해 위의 Fetch event를 해준다.
백그라운드에서도 측정이 가능해야한다
- 위의 startActivityUpdates의 경우 동작데이터의 추적을 비동기적으로 시작한다. handler 지정된 블록을 실행하고 queue 장치에 적용되는 현재 모션을 보고. 하지만 앱이 일시중지될때는 업데이트를 제공하지 않고 앱이 중지되었을때의 업데이트 사항들 중 마지막껏만 앱실행이 재개될때 앱에 전달된다고 공식문서에 써있다. 하지만
capabilites에서 background를 location updates를 켜주면 백그라운드에서도 location updates를 통해 motion activity들을 background에서도 업데이트가 가능하다.
🐛발생 🚨🚨🚨🚨🚨🚨🚨🚨
1. 측정이 이상함..이상하다는게 모냐면 갑자기 10초안지났는데 값이 업뎃되자마자 0으로 변하는 현상 발생.
-> 그 이유는 queryPedometerData는 비동기로 호출됨.
open func queryPedometerData(from start: Date, to end: Date, withHandler handler: @escaping CMPedometerHandler)
이렇게 생김!! escaping이 있다.흠..어캐하지? 두가지 방법이 떠오름. 1. 10초가 아닌 60초처럼 길게하면 버그가 안생기지 않을까..?
-> 비동기처리를 동기처럼 await을 사용하여 데이터를 받아오고 처리가 끝나면 그때부터 10초를 세어준다.
위와 같이 Task로 관리.
'SWIFT개발' 카테고리의 다른 글
CoreLocation과 Battery의 관계 (1) 2024.04.21 CoreLocation & MapKit (1) 2024.04.19 go back to basic - @main 플젝만들면 항상생기는 파일 이건 몰까? (0) 2024.03.01 some(Opaque Type)&any Keyword (1) 2024.02.29 근본으로 돌아가자(4)-@State,@StateObject,@ObservedObject (2) 2024.02.27 다음글이전글이전 글이 없습니다.댓글