HealthKit & CoreMotion

Sonjh1306·2023년 9월 4일

✔️ HealthKit

사용자의 개인 정보 및 제어를 유지하면서 건강 및 피트니스 데이터의 엑세스하고 공유할 수 있는 프레임워크

HKHealthStore

  • HealthKit에서 관리하는 모든 데이터의 엑세스 포인트
  • HealthKit 데이터를 공유하거나 읽을 수 있는 권한을 요청
  • 권한이 부여되면 HealthKitStore를 사용하여 스토어에 새 샘플을 저장하거나 저장한 샘플들을 관리 가능
  • HKHealthStore를 사용하여 쿼리를 시작, 중지 및 관리 가능
  • Accessing healthKit
// 앱의 승인 상태를 반환
func authorizationStatus(for: HKObjectType) -> HKAuthorizationStatus

// 현재 디바이스에서 HealthKit을 사용 가능 여부
class func isHealthDataAvailable() -> Bool

// 지정된 데이터 유형을 저장하고 읽을 수 있는 권한 요청
func requestAuthorization(toShare: Set<HKSampleType>?, read: Set<HKObjectType>?, completion: (Bool, Error?) -> Void)

// 지정된 데이터 유형을 저장하고 읽을 수 있는 권한을 비동기적으로 요청
func requestAuthorization(toShare: Set<HKSampleType>, read: Set<HKObjectType>)
  • Querying HealthKit data
// 제공된 쿼리 실행 시작
func execute(_ query: HKQuery)

// 쿼리 실행 중지
func stop(_ query: HKQuery)

HKStatisticsCollectionQuery

  • 고정 시간 간격 동안 여러 통계 쿼리를 수행하는 쿼리
  • Creating Statistics Collection Objects
// 일정 시간 간격 동안 지정된 계산을 수행하도록 
init(quantityType: HKQuantityType, // 검색할 샘플 유형(ex. stepCount)
quantitySamplePredicate: NSPredicate?, // 쿼리 반환 결과
options: HKStatisticsOptions, // 수행된 통계 계산 병합 방법
anchorDate: Date, // 시간 간격의 시작 시간
intervalComponents: DateComponents) // 시간 간격
  • Getting and Setting Results Handlers
// 쿼리의 초기 결과에 대한 핸들러
var initialResultsHandler: ((HKStatisticsCollectionQuery, HKStatisticsCollection?, Error?) -> Void)? { get set }

// HealthKit Store 업데이트를 모니터링 하기 위한 핸들러
var statisticsUpdateHandler: ((HKStatisticsCollectionQuery, HKStatistics?, HKStatisticsCollection?, Error?) -> Void)? { get set }
  • Getting Property Data
// 시간 간격 기준 날짜
var anchorDate: Date { get }

// 시간 간격
var intervalComponents: DateComponents { get }

// 데이터 병합 방식
var options: HKStatisticsOptions { get }

HKStatisticsCollection

  • 지정된 시간 간격 동안 계산된 통계 모음 결과를 관리하는 객체
  • Accessing Statistics Collections
// 전체 통계 리스트 반환
func statistics() -> [HKStatistics]

// 지정된 날짜가 포함된 통계 반환
func statistics(for: Date) -> HKStatistics?

// 지정 시간 구간에 대한 통계 리스트 반환
func enumerateStatistics(from: Date, to: Date, with: (HKStatistics, UnsafeMutablePointer<ObjCBool>) -> Void)

Sample

import UIKit
import HealthKit

class ViewController: UIViewController {
    
    private let healthStore = HKHealthStore()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        accessStepCount()
    }

    func accessStepCount() {
        let healthKitTypes: Set = [HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!]

        // 디바이스에서 HealthKit 사용 가능 여부 확인
        if HKHealthStore.isHealthDataAvailable() {
            // 권한 요청 화면 팝업 여부(처음 1회만)
            healthStore.requestAuthorization(toShare: nil, read: healthKitTypes) { (success, error) in
                if error != nil {
                    print(error!.localizedDescription)
                } else {
                    if success {
                        self.getSteps { (result) in
                            DispatchQueue.main.async { [self] in
                                let steps = String(result)
                                print(steps)
                            }
                        }
                    } else {
                        print("not popup authorization view")
                    }
                }
            }
        } else {
            print("")
        }
        
    }
    
    private func getSteps(completion: @escaping (Double) -> Void) {
		// 수집 데이터 identifier 지정
        let type = HKQuantityType.quantityType(forIdentifier: .stepCount)!
        
        let now = Date()
        let startOfDay = Calendar.current.startOfDay(for: now)
        var interval = DateComponents()
        interval.day = 1
        
		// 실행할 쿼리 생성
        let query = HKStatisticsCollectionQuery(quantityType: type,
                                                quantitySamplePredicate: nil,
                                                options: [.cumulativeSum],
                                                anchorDate: startOfDay,
                                                intervalComponents: interval)
        query.initialResultsHandler = { _, result, error in
            var resultCount = 0.0
			// 지정한 시간동안의 통계 정보 얻기
            result!.enumerateStatistics(from: startOfDay, to: now, with: { statistics, _ in
                if let sum = statistics.sumQuantity() {
                    resultCount = sum.doubleValue(for: HKUnit.count())
                }
                
                DispatchQueue.main.async {
                    completion(resultCount)
                }
            })
        }
        
        query.statisticsUpdateHandler = { query, statistics, statisticsCollection, error in
            if let sum = statistics?.sumQuantity() {
                let resultCount = sum.doubleValue(for: HKUnit.count())
                
                DispatchQueue.main.async {
                    completion(resultCount)
                }
            }
        }
        healthStore.execute(query)
    }
}

✔️ Core Motion

가속도계, 자이로스코프, 보수계, 자력계 및 기압계를 포함하여 iOS 장치의 온보드 하드웨어에서 모션 및 환경 관련 데이터를 관리할 수 있게 해주는 프레임워크

  • Core Motion 에서 걸음 관련 데이터를 제공 받을 수 있는 클래스는 총 3개
    1. CMPedometer: 실시간 걸음 데이터 정보 제공
    2. CMPedometerData: 사용자가 도보로 이동한 거리 정보 제공
    3. CMPedometerEvent: 사용자의 보행자 활동 변화 정보 제공

CMPedometer

  • Determining Pedometer Availability
// 현재 디바이스에서 걸음 수 카운팅 사용 가능 여부
class func isStepCountingAvailable() -> Bool

// 현재 디바이스에서 거리 측정 사용 가능 여부
class func isDistanceAvailable() -> Bool

// 현재 디바이스에서 층 수 측정 사용 가능 여부
class func isFloorCountingAvailable() -> Bool

// 현재 디바이스에서 사용자의 페이스 정보 사용 가능 여부
class func isPaceAvailable() -> Bool

// 현재 디바이스에서 만보계 이벤트 사용 가능 여부
class func isPedometerEventTrackingAvailable() -> Bool

// 앱이 만보계 데이터를 수집할 권한이 있는 지 여부
class func authorizationStatus() -> CMAuthorizationStatus

// 모션 관련 기능에 대한 인증 상태
enum CMAuthorizationStatus
  • Gathering Live Pedometer Data
// 보행자 관련 데이터를 전달 시작
func startUpdates(from: Date, withHandler: CMPedometerHandler)

// 보행자 관련 데이터 전달 중지
func stopUpdates()

// 만보계 이벤트 전달 시작
func startEventUpdates(handler: CMPedometerEventHandler)

// 만보계 이벤트 전달 중지
func stopEventUpdates()

// 만보계 관련 데이터 처리 블록
typealias CMPedometerHandler

// 만보계 이벤트 관련 데이터 처리 블록
typealias CMPedometerEventHandler
  • Fetching Historical Pedometer Data
// 지정된 Date 사이의 만보계 데이터 수집(최대 7일 가능)
// from의 날짜가 현재 기준 7일 이내 설정
func queryPedometerData(from: Date, to: Date, withHandler: CMPedometerHandler)

Sample

import UIKit
import CoreMotion

class ViewController: UIViewController {
    
    private let pedometer = CMPedometer()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if CMPedometer.isStepCountingAvailable() {
            getTodayStepCount()
            getWeekStepCount()
        }
    }

	// 당일 걸음 수 데이터 가져오기
    private func getTodayStepCount() {
        
        pedometer.startUpdates(from: Calendar.current.startOfDay(for: Date()), withHandler: { [weak self] (data, error) in
            if error != nil {
                print("Can't Update Today Step Count")
            }
            
            if let stepData = data {
                let steps = stepData.numberOfSteps.stringValue
                DispatchQueue.main.async {
                    print("Today: \(steps)")
                }
            }
            
        })
    }

    // 지정 날짜 걸음 수 데이터 가져오기(최대 7일)
    private func getWeekStepCount() {
        let calendar = Calendar.current
        
        guard let startDay = calendar.date(byAdding: .day, value: -6, to: calendar.startOfDay(for: Date()), wrappingComponents: false),
              let endDay = calendar.date(byAdding: .day, value: 1, to: calendar.startOfDay(for: Date()), wrappingComponents: false) else { return }

        pedometer.queryPedometerData(from: startDay, to: endDay, withHandler: { [weak self] (data, error) in
            if error != nil {
                print("Can't Update Weeks Step Count")
            }
            
            if let stepData = data {
                let steps = stepData.numberOfSteps.stringValue
                DispatchQueue.main.async {
                    print("Weeak: \(steps)")
                }
            }
        })
    }
    
}

✔️ HealthKit과 Core Motion 비교

스크린샷 2023-09-04 오전 10 56 45
profile
iOS 개발자

0개의 댓글