본문 바로가기
iOS_Swift 앱개발👍

[iOS_Swift] HealthKit - 헬스킷 : 수면 데이터 마스터 (With HKCategoryType)_ 41

by 개발하는윤기사 2023. 11. 13.
728x90
반응형

 

안녕하세요~~ 개발하는 윤기사입니다!

 

이번 포스팅은 저번 포스팅에 이어서 헬스킷 내의 수면 데이터를 다뤄 볼 건데요!

 

저번 포스팅에서는 HKQuantityType을 이용해서 걸음수, 칼로리, 심박수 등 값으로 이루어져 있는 데이터를 다뤘다면!!

 

* 저번 포스팅 링크 첨부⭐️

 

[iOS_Swift] HealthKit - 헬스킷 : 걸음수, 칼로리, 심박수 다뤄보자! (With HKQuantityType)_ 40

안녕하세요~~ 개발하는 윤기사입니다!! 이번 포스팅은 저번 헬스킷 1편에 이어서 2편입니다!! [iOS_Swift] HealthKit - 헬스킷 : 건강 데이터 사용해보자! _ 36 안녕하세요!! 이번 글에서는 애플 헬스킷(Hea

swiftyun.tistory.com

 

 

 

이번 포스팅에서는 HKCategoryType으로 애플워치로 기록된 수면 데이터를 다뤄보도록 할게요!

 

이전 포스팅과 마찬가지로, HKSampleQuery를 이용해 데이터를 가져올 겁니다.

 

 

 

 

HKCategoryType

가능한 작은 값 집합의 값을 포함하는 샘플을 식별하는 유형입니다.

 

 

 

HKCategoryType 중에서 HKCategoryTypeIdentifier가 있는데, 다양한 타입이 있으니 참고 링크 하나 남겨드립니다!

참고 : https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis

 

HKCategoryValueSleepAnalysis | Apple Developer Documentation

Categories that represent the result of a sleep analysis.

developer.apple.com

 

 

HKCategoryTypeIdentifier

 

 

저희가 사용할 건 그중에서 sleepAnalysis. 즉 수면 분석을 사용할 겁니다!

 

 

애플 공식문서에 보면 수면 분석이 뭔가 알록달록하게 생겼죠?

수면 레벨

 

애플 워치 내에 수면 기록하는 기능이 있는데,

 

아래와 같이 inBed, asleepUnspecified, awake, asleepCore, asleepDeep, asleepREM으로 단계가 나뉩니다.

 

그래서 사용자가 언제 수면 중에 깼는지, 램 수면, 깊은 수면, 얕은 수면은 언제 들었는지를 시간으로 확인할 수 있습니다!

//수면 레벨
case inBed = 0
case asleepUnspecified = 1
case awake = 2
case asleepCore = 3
case asleepDeep = 4
case asleepREM = 5

 

 

 

 

바로 코드로 실행시켜 볼까요?

 

1️⃣ HealthKit 내의 HKCategoryType의 .sleepAnalysis의 값을 HKCategorySample의 배열을 만들어 담아보겠습니다! +_+

/**
 - note: HealthKit CategoryType 데이터 정보 호출
 - parameters:
    - startDate: 시작 날짜
    - endDate: 끝난 날짜
    - type: 쿼리 타입 .sleepAnalysis(수면)
 */
public func getCatogoryTypeValues(startDate: Date, endDate: Date, type: HKCategoryTypeIdentifier, completion: @escaping([HKCategorySample])->()) {

    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)
    let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)
    let quantityType = HKObjectType.categoryType(forIdentifier: type)!
    let query = HKSampleQuery(sampleType: quantityType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: [sortDescriptor]) { (query, result, error) -> Void in

        var sleepList: [HKCategorySample] = []

        for (_, sleepSample) in (result ?? []).enumerated() {
            guard let data: HKCategorySample = sleepSample as? HKCategorySample else { return }
            sleepList.append(data)
        }
        completion(sleepList)

    }
    healthStore.execute(query)
}

 

 

2️⃣ 꺼내온 수면 데이터 값을 저장하기 위한 SleepHistoryModel도 하나 만들어줄게요!

여기서 저희가 필요한 것은 수면 시작 시간, 수면 종료 시간, 수면 데이터 각각의 고유 Uuid, 수면 레벨이 되겠죠!?

struct SleepHistoryModel {
    
    var sleepStartDateTime: Date = Date()
    var sleepEndDateTime: Date = Date()
    var recordUuid : String = ""
    var sleepLevel: Int = 0
    
    public init(sleepStartDateTime: Date, sleepEndDateTime: Date, sleepLevel: Int, recordUuid:  String) { 
        self.sleepStartDateTime = sleepStartDateTime
        self.sleepEndDateTime = sleepEndDateTime
        self.sleepLevel = sleepLevel
        self.recordUuid  = recordUuid
    }
     
}

 

 

3️⃣ getSleepData(_:)라는 메서드를 하나 만들어서 위에서 만들었던 getCatogoryTypeValues(_:)를 실행시켜 받아온 [HKCategorySample]의 for문을 돌아 각각 SleepModel에 담아주면 됩니다.

 

+ 덤으로 sort(by: )를 이용해서 정렬도 해줄게요!

public var completionHandler:(_ type: sleepAnalysisType, _ dataList: [Any])->() = { _, _ in }

/** 헬스킷 수면 데이터 조회 */
public func getSleepData(_ startDate: Date? = nil) {

    let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date()) ?? Date()
    HealthKitManager.shared().getCatogoryTypeValues(startDate: startDate, endDate: Date(), type: .sleepAnalysis) { dataList in

        var sleepDataList = [SleepHistoryModel]()

        for data in dataList {
            let sleepStartDateTime = data.startDate
            let sleepEndDateTime   = data.endDate
            let sleepLevel         = data.value
            let recordUuid         = "\(data.uuid)"
            var sleepData = SleepHistoryModel(sleepStartDateTime: sleepStartDateTime, sleepEndDateTime: sleepEndDateTime, sleepLevel: sleepLevel, recordUuid: recordUuid)
            sleepDataList.append(sleepData)
        }

        sleepDataList.sort(by: { $0.sleepStartDateTime < $1.sleepStartDateTime })
        self.completionHandler(.sleep, sleepDataList)
    }
}

 

 

 

이렇게 헬스킷 내에 있는 수면 데이터를 꺼내와서 원하는 타입으로 바꿔봤는데요, 생각보다 간단하죠?

 

걸음수나 칼로리같이 값으로 표현되어 있는 HKQuantityType과 굉장히 비슷해서 다루기가 쉽습니다!

 

 

 

이번 포스팅은 여기서 마치겠습니다!! 

 

날씨가 많이 추워졌는데, 다들 감기조심하시고! 빡코딩 하시길 바랄게요! :)

 

 

728x90
반응형