Tüm Yazılar
KategoriiOS
Okuma Süresi
20 dk
Yayın Tarihi
...
Kelime Sayısı
1.258kelime

Kahveni hazırla - bu içerikli bir makale!

HealthKit entegrasyonu ile sağlık verileri okuma/yazma, workout session'ları, background delivery ve watchOS entegrasyonu.

HealthKit ile Sağlık ve Fitness Uygulamaları Geliştirme

Apple Health, dünya genelinde milyonlarca kullanıcının sağlık verilerini sakladığı merkezi platform. HealthKit framework'ü ile bu verilere erişerek, sağlık ve fitness uygulamaları geliştirebilirsin. Kalp atış hızından adım sayısına, uyku analizinden workout takibine kadar kapsamlı bir API sunar.

💡 Hızlı Not: HealthKit kullanmak için Apple Developer Program üyeliği ve uygulamada HealthKit capability'si aktif edilmeli. Ayrıca App Store Review Guidelines 5.1.3 — sağlık verilerinin reklam amaçlı kullanılması yasaktır.

İçindekiler

  1. HealthKit Temel Kavramlar
  2. Authorization ve İzinler
  3. Sağlık Verisi Okuma
  4. Sağlık Verisi Yazma
  5. HKQuery Tipleri
  6. Workout Sessions
  7. Background Delivery
  8. SwiftUI Charts ile Görselleştirme
  9. watchOS Entegrasyonu
  10. Privacy Best Practices

HealthKit Temel Kavramlar {#temel-kavramlar}

Kavram
Açıklama
Örnek
HKObjectType
Veri tipi tanımı
steps, heartRate, sleep
HKQuantityType
Sayısal değerler
adım (count), kalori (kcal)
HKCategoryType
Kategorik değerler
uyku durumu, adet döngüsü
HKSample
Tek veri noktası
10:00'da 72 bpm kalp atışı
HKStatistics
İstatistik
Günlük toplam adım
HKUnit
Ölçü birimi
count, kcal, mg/dL

Authorization ve İzinler {#authorization}

swift
1import HealthKit
2 
3class HealthKitManager {
4 let healthStore = HKHealthStore()
5 
6 // Okuma ve yazma izinleri
7 func requestAuthorization() async throws {
8 guard HKHealthStore.isHealthDataAvailable() else {
9 throw HealthError.notAvailable
10 }
11 
12 let readTypes: Set<HKObjectType> = [
13 HKQuantityType(.stepCount),
14 HKQuantityType(.heartRate),
15 HKQuantityType(.activeEnergyBurned),
16 HKQuantityType(.distanceWalkingRunning),
17 HKCategoryType(.sleepAnalysis),
18 HKQuantityType(.bodyMass),
19 ]
20 
21 let writeTypes: Set<HKSampleType> = [
22 HKQuantityType(.stepCount),
23 HKQuantityType(.activeEnergyBurned),
24 HKQuantityType(.bodyMass),
25 ]
26 
27 try await healthStore.requestAuthorization(toShare: writeTypes, read: readTypes)
28 }
29}

Sağlık Verisi Okuma {#veri-okuma}

swift
1// Bugünün adım sayısı
2func getTodaySteps() async throws -> Double {
3 let stepType = HKQuantityType(.stepCount)
4 let now = Date()
5 let startOfDay = Calendar.current.startOfDay(for: now)
6 let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now)
7 
8 let statistics = try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<HKStatistics, Error>) in
9 let query = HKStatisticsQuery(
10 quantityType: stepType,
11 quantitySamplePredicate: predicate,
12 options: .cumulativeSum
13 ) { _, statistics, error in
14 if let error { continuation.resume(throwing: error) }
15 else if let statistics { continuation.resume(returning: statistics) }
16 else { continuation.resume(throwing: HealthError.noData) }
17 }
18 healthStore.execute(query)
19 }
20 
21 return statistics.sumQuantity()?.doubleValue(for: .count()) ?? 0
22}
23 
24// Kalp atış hızı - son 7 gün
25func getHeartRateData(days: Int = 7) async throws -> [(date: Date, bpm: Double)] {
26 let heartRateType = HKQuantityType(.heartRate)
27 let startDate = Calendar.current.date(byAdding: .day, value: -days, to: Date())!
28 let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date())
29 let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
30 
31 return try await withCheckedThrowingContinuation { continuation in
32 let query = HKSampleQuery(
33 sampleType: heartRateType,
34 predicate: predicate,
35 limit: HKObjectQueryNoLimit,
36 sortDescriptors: [sortDescriptor]
37 ) { _, samples, error in
38 if let error { continuation.resume(throwing: error); return }
39 let results = (samples as? [HKQuantitySample])?.map { sample in
40 (date: sample.startDate, bpm: sample.quantity.doubleValue(for: .init(from: "count/min")))
41 } ?? []
42 continuation.resume(returning: results)
43 }
44 healthStore.execute(query)
45 }
46}

Sağlık Verisi Yazma {#veri-yazma}

swift
1// Kilo kaydet
2func saveBodyMass(kg: Double, date: Date = Date()) async throws {
3 let type = HKQuantityType(.bodyMass)
4 let quantity = HKQuantity(unit: .gramUnit(with: .kilo), doubleValue: kg)
5 let sample = HKQuantitySample(type: type, quantity: quantity, start: date, end: date)
6 try await healthStore.save(sample)
7}
8 
9// Workout kaydet
10func saveWorkout(type: HKWorkoutActivityType, duration: TimeInterval, calories: Double) async throws {
11 let workout = HKWorkout(
12 activityType: type,
13 start: Date().addingTimeInterval(-duration),
14 end: Date(),
15 duration: duration,
16 totalEnergyBurned: HKQuantity(unit: .kilocalorie(), doubleValue: calories),
17 totalDistance: nil,
18 metadata: nil
19 )
20 try await healthStore.save(workout)
21}

HKQuery Tipleri {#query-tipleri}

Query
Kullanım
Özellik
HKSampleQuery
Tek seferlik veri çekme
Basit okuma
HKStatisticsQuery
İstatistik (sum, avg)
Toplam adım
HKStatisticsCollectionQuery
Zaman serisi
Haftalık grafik
HKAnchoredObjectQuery
Delta güncelleme
Son değişiklikler
HKObserverQuery
Gerçek zamanlı
Canlı veri
HKActivitySummaryQuery
Activity rings
Move/Exercise/Stand

Workout Sessions {#workout}

swift
1// watchOS Workout Session
2import HealthKit
3 
4class WorkoutManager: NSObject, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {
5 let healthStore = HKHealthStore()
6 var session: HKWorkoutSession?
7 var builder: HKLiveWorkoutBuilder?
8 
9 func startWorkout(type: HKWorkoutActivityType) async throws {
10 let config = HKWorkoutConfiguration()
11 config.activityType = type
12 config.locationType = .outdoor
13 
14 session = try HKWorkoutSession(healthStore: healthStore, configuration: config)
15 builder = session?.associatedWorkoutBuilder()
16 builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: config)
17 
18 session?.delegate = self
19 builder?.delegate = self
20 
21 let startDate = Date()
22 session?.startActivity(with: startDate)
23 try await builder?.beginCollection(at: startDate)
24 }
25 
26 func endWorkout() async throws {
27 session?.end()
28 try await builder?.endCollection(at: Date())
29 try await builder?.finishWorkout()
30 }
31 
32 func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
33 // State değişikliği handle et
34 }
35 
36 func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
37 // Yeni veri geldi
38 }
39}

Background Delivery {#background}

swift
1// Uygulama arka plandayken sağlık verisi güncellemesi al
2func enableBackgroundDelivery() {
3 let stepType = HKQuantityType(.stepCount)
4 healthStore.enableBackgroundDelivery(for: stepType, frequency: .hourly) { success, error in
5 if success {
6 print("Background delivery enabled for steps")
7 }
8 }
9 
10 // Observer query ile veri dinle
11 let query = HKObserverQuery(sampleType: stepType, predicate: nil) { _, completionHandler, error in
12 // Yeni adım verisi geldi - UI güncelle veya notification gönder
13 self.refreshStepCount()
14 completionHandler()
15 }
16 healthStore.execute(query)
17}

SwiftUI Charts ile Görselleştirme {#charts}

swift
1import SwiftUI
2import Charts
3 
4struct StepChartView: View {
5 let data: [(date: Date, steps: Int)]
6 
7 var body: some View {
8 Chart(data, id: \.date) { item in
9 BarMark(
10 x: .value("Tarih", item.date, unit: .day),
11 y: .value("Adım", item.steps)
12 )
13 .foregroundStyle(item.steps >= 10000 ? .green : .blue)
14 }
15 .chartYAxis {
16 AxisMarks(position: .leading)
17 }
18 .frame(height: 200)
19 }
20}

watchOS Entegrasyonu {#watchos}

Apple Watch, sağlık verilerinin birincil kaynağıdır. Watch Connectivity framework ile iPhone-Watch arası veri senkronizasyonu yapılabilir.

Privacy Best Practices {#privacy}

  1. Minimum veri iste — sadece gereken tipleri
  2. Açıklama ekle — Info.plist'te NSHealthShareUsageDescription ve NSHealthUpdateUsageDescription
  3. Şifreleme — sağlık verilerini iletirken TLS kullan
  4. Silme desteği — kullanıcı verilerini silebilmeli
  5. Reklam yasağı — sağlık verileri reklam amaçlı kullanılamaz (App Store guideline 5.1.3)

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var: **Kaynaklar:** - [Apple: HealthKit Documentation](https://developer.apple.com/documentation/healthkit) - [WWDC22: What's new in HealthKit](https://developer.apple.com/videos/play/wwdc2022/10005/) - [App Store Review Guidelines 5.1.3](https://developer.apple.com/app-store/review/guidelines/#health-and-health-research)

Etiketler

#healthkit#health#fitness#apple-watch#workout#ios#watchos
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz