Slide 1

Slide 1 text

Kazuhiro Kamakura 1SJPSJUJ[JOH)FBMUI %FWFMPQJOHB1FSTPOBMJ[FE"QQ ݈߁ୈҰʂ ࣗ෼ઐ༻ͷݸਓΞϓϦ։ൃ

Slide 2

Slide 2 text

Kazuhiro Kamakura ח૔࿨߂ 9!ZPZPLL55 LY Corporation

Slide 3

Slide 3 text

Do you do personal development? ࠷ۙɺݸਓ։ൃ͍ͯ͠·͔͢ʂʁ

Slide 4

Slide 4 text

Some people might say “I haven't done any personal development lately.” Ҏલ͸͍͚ͯͨ͠Ͳɺ࠷ۙ͸͍ͯ͠ͳ͍ɾɾ

Slide 5

Slide 5 text

I want only one function. However, that would likely result in rejection from the App Review. ̍ͭͷػೳ͚ͩཉ͍͚͠ͲɺͦΕͰ͸ϦδΣΫτ͞Εͦ͏ɾɾ

Slide 6

Slide 6 text

I have a suggestion! 💡

Slide 7

Slide 7 text

Why don't you develop your own app only for yourself? ࣗ෼ͷͨΊ͚ͩͷΞϓϦ։ൃ͸Ͳ͏Ͱ͠ΐ͏ʂʁ

Slide 8

Slide 8 text

I have created an app that only counts my steps. 🏃. →

Slide 9

Slide 9 text

Background ࡞ͬͨഎܠ • I know we need to walk for our health. • But I rarely go out. 🏃..

Slide 10

Slide 10 text

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೥౰࣌

Slide 11

Slide 11 text

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೥౰࣌

Slide 12

Slide 12 text

So, how did I make it?ɹ 🔨☺ Ͱ͸ͲͷΑ͏ʹ࡞͍͔ͬͯͬͨʁ

Slide 13

Slide 13 text

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 ->

Slide 14

Slide 14 text

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.

Slide 15

Slide 15 text

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)") // ଞͷσʔλ΋ಉ༷ʹΞΫηεՄೳ } } } }

Slide 16

Slide 16 text

I can write the program with ChatGPT $IBU(15ʹฉ͚͹؆୯ʹ͔͚·͢ʂ Thank you!

Slide 17

Slide 17 text

HealthKit As you know, we can get information from HealthKit ← 📱 Same as this ->

Slide 18

Slide 18 text

Which one should I use? 🤔 Ͱ͸ͲͪΒΛબͿ͔ʁ

Slide 19

Slide 19 text

HealthKit method is popular. And, it’s used for the company’s app. So, I use Health Kit.

Slide 20

Slide 20 text

We can do a lot more🚶

Slide 21

Slide 21 text

How to use HealthKit • Add Capability • Add permission settings for HealthKit data access to info.plist

Slide 22

Slide 22 text

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) } }

Slide 23

Slide 23 text

Completion of the iOS version This is what it looks like when displayed in Swift Charts →

Slide 24

Slide 24 text

My App Icon ->

Slide 25

Slide 25 text

But, I didn’t open the iOS app ❌ ͔͠͠ɺiOS App͸։͔ͣɾɾɾ

Slide 26

Slide 26 text

So, I created a Watch widget that I can always see.

Slide 27

Slide 27 text

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…

Slide 28

Slide 28 text

Xcode 15 has the capability🎉 Xcode 15 gets HealthKit capability!!

Slide 29

Slide 29 text

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) } }

Slide 30

Slide 30 text

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) -> ()) { 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

Slide 31

Slide 31 text

I can see it on the main screen now! I can always see it on my Apple Watch!

Slide 32

Slide 32 text

As a result I can always walk over 4,000 steps a day 🎉 ← 4000 Steps

Slide 33

Slide 33 text

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.

Slide 34

Slide 34 text

Enjoy Programming!

Slide 35

Slide 35 text

Thank you!