Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Prioritizing Health: Developing a Personalized App

tatetate55
March 24, 2024
390

Prioritizing Health: Developing a Personalized App

tatetate55

March 24, 2024
Tweet

Transcript

  1. Some people might say “I haven't done any personal development

    lately.” Ҏલ͸͍͚ͯͨ͠Ͳɺ࠷ۙ͸͍ͯ͠ͳ͍ɾɾ
  2. I want only one function. However, that would likely result

    in rejection from the App Review. ̍ͭͷػೳ͚ͩཉ͍͚͠ͲɺͦΕͰ͸ϦδΣΫτ͞Εͦ͏ɾɾ
  3. Why don't you develop your own app only for yourself?

    ࣗ෼ͷͨΊ͚ͩͷΞϓϦ։ൃ͸Ͳ͏Ͱ͠ΐ͏ʂʁ
  4. Background ࡞ͬͨഎܠ • I know we need to walk for

    our health. • But I rarely go out. 🏃..
  5. I have an incentive Πϯηڅ༩ͷࢧڅʂ I can receive an incentive

    from my company if I walk over 4,000 steps a day! https://about.yahoo.co.jp/info/blog/20210719/walking.html ※2021೥౰࣌
  6. I have an incentive Πϯηڅ༩ͷࢧڅʂ I can receive an incentive

    from my company if I walk over 4,000 steps a day! https://about.yahoo.co.jp/info/blog/20210719/walking.html I'm gonna do it! ※2021೥౰࣌
  7. How the app measures the number of steps There are

    two patterns 1. CMPedometer of CoreMotion 2. HealthKit I won't use it this time ->
  8. CMPedometer of CoreMotion 1. It can measure in real time

    2. It can measure the number of steps on that device. 3. It can count steps from iOS 8.
  9. How to use CMPedometer of CoreMotion import CoreMotion class PedometerManager

    { let pedometer = CMPedometer() // ϖυϝʔλʔ͕ར༻Մೳ͔νΣοΫ func isPedometerAvailable() -> Bool { return CMPedometer.isStepCountingAvailable() } // ϦΞϧλΠϜͰา਺Λऔಘ func startPedometerUpdates() { guard CMPedometer.isStepCountingAvailable() else { print("Step counting is not available.") return } pedometer.startUpdates(from: Date()) { (data, error) in guard error == nil else { print("There was an error starting pedometer updates: \(error!.localizedDescription)") return } if let pedometerData = data { print("Steps taken: \(pedometerData.numberOfSteps)") // ଞͷσʔλ΋ಉ༷ʹΞΫηεՄೳ } } } }
  10. How to use HealthKit • Add Capability • Add permission

    settings for HealthKit data access to info.plist
  11. How to use import HealthKit class HealthKitManager { let healthStore

    = HKHealthStore() // HealthKitͷηοτΞοϓ init() { if HKHealthStore.isHealthDataAvailable() { let allTypes = Set([HKObjectType.quantityType(forIdentifier: .stepCount)!]) healthStore.requestAuthorization(toShare: nil, read: allTypes) { (success, error) in if !success { // ΤϥʔϋϯυϦϯά } } } } // ಛఆͷ೔ͷา਺Λऔಘ func getSteps(forDate date: Date, completion: @escaping (Double) -> Void) { guard let stepCountType = HKQuantityType.quantityType(forIdentifier: .stepCount) else { completion(0) return } let startOfDay = Calendar.current.startOfDay(for: date) let endOfDay = Calendar.current.date(byAdding: .day, value: 1, to: startOfDay) let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: endOfDay, options: .strictStartDate) let query = HKStatisticsQuery(quantityType: stepCountType, quantitySamplePredicate: predicate, options: .cumulativeSum) { (query, statistics, error) in var steps: Double = 0 if error != nil { // ΤϥʔϋϯυϦϯά } else if let quantity = statistics?.sumQuantity() { steps = quantity.doubleValue(for: HKUnit.count()) } DispatchQueue.main.async { completion(steps) } } healthStore.execute(query) } }
  12. Completion of the iOS version This is what it looks

    like when displayed in Swift Charts →
  13. But Xcode 14 doesn’t have HealthKit capability • Watch’s Widget

    of Xcode 14 doesn’t have HealthKit capability. • Therefore, I need to transfer data from my watch or iPhone. ← Nothing…
  14. I can get the same method as iOS! ΍Γํ͸iOSͱಉ͡ʂ //

    HealthStoreʹࠓ೔ͷา਺Λऔಘ͢ΔϝιουΛ௥Ճ extension HealthStore { func fetchTodaysSteps(completion: @escaping (Int) -> Void) { // HealthKitετΞ͕͋Δ͜ͱΛ֬ೝ guard let healthStore = healthStore else { return } // า਺λΠϓΛఆٛ͠ɺࠓ೔ͷ೔෇ൣғΛઃఆ let stepType = HKQuantityType.quantityType(forIdentifier: .stepCount)! let now = Date() let startOfDay = Calendar.current.startOfDay(for: now) // ΫΤϦͷ೔෇ൣғΛઃఆ͢ΔͨΊͷड़ޠΛ࢖༻ let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now, options: .strictStartDate) // า਺ͷ߹ܭΛऔಘ͢ΔͨΊͷΫΤϦΛ࡞੒ let query = HKStatisticsQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum) { _, statistics, _ in let steps = statistics?.sumQuantity()?.doubleValue(for: HKUnit.count()) ?? 0 completion(Int(steps)) } // ΫΤϦΛ࣮ߦ healthStore.execute(query) } }
  15. Reload & Display 3FMPBE struct NumberStepsWatchExtensionEntryView : View { var

    entry: Provider.Entry var body: some View { VStack { Text(String(Date().timetoString())) .font(.footnote) Text(String(entry.steps)) } .containerBackground(for: .widget) { Color.white } } } func getTimeline(in context: Context, completion: @escaping (Timeline<StepEntry>) -> ()) { let healthStore = HealthStore() healthStore.fetchTodaysSteps { stepCount in let currentDate = Date() let entries = [ StepEntry(date: currentDate, steps: stepCount) ] // ࣍ͷߋ৽࣌ࠁΛݱࡏ͔Β5෼ޙʹઃఆ let nextUpdateDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)! let timeline = Timeline(entries: entries, policy: .after(nextUpdateDate)) completion(timeline) } } %JTQMBZ
  16. I can see it on the main screen now! I

    can always see it on my Apple Watch!
  17. Conclusion • It is di ffi cult to achieve exercise

    with the goal of health alone. • I enjoy solving my own problems with programming. • Especially for watchOS, there are still very few in the world.