{"id":15527703,"url":"https://github.com/kvs-coder/healthkitreporter","last_synced_at":"2025-10-06T14:45:31.096Z","repository":{"id":38835954,"uuid":"295367086","full_name":"kvs-coder/HealthKitReporter","owner":"kvs-coder","description":"HealthKitReporter. A wrapper for HealthKit framework. Helps to write or read data from Apple Health via HealthKit framework.","archived":false,"fork":false,"pushed_at":"2024-12-11T22:18:54.000Z","size":544,"stargazers_count":85,"open_issues_count":8,"forks_count":24,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-23T08:27:06.089Z","etag":null,"topics":["apple","apple-health","cocoapods","health","healthkit","healthkit-framework","healthkit-objects","healthkitreporter","ios","swift"],"latest_commit_sha":null,"homepage":"https://cocoapods.org/pods/HealthKitReporter","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kvs-coder.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":"FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["VictorKachalov"]}},"created_at":"2020-09-14T09:25:59.000Z","updated_at":"2025-07-18T21:02:19.000Z","dependencies_parsed_at":"2024-06-21T20:23:45.653Z","dependency_job_id":"a608d933-c8e7-4609-8205-559d802360d1","html_url":"https://github.com/kvs-coder/HealthKitReporter","commit_stats":null,"previous_names":["victorkachalov/healthkitreporter"],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/kvs-coder/HealthKitReporter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kvs-coder%2FHealthKitReporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kvs-coder%2FHealthKitReporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kvs-coder%2FHealthKitReporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kvs-coder%2FHealthKitReporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kvs-coder","download_url":"https://codeload.github.com/kvs-coder/HealthKitReporter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kvs-coder%2FHealthKitReporter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278628715,"owners_count":26018476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple","apple-health","cocoapods","health","healthkit","healthkit-framework","healthkit-objects","healthkitreporter","ios","swift"],"created_at":"2024-10-02T11:08:38.909Z","updated_at":"2025-10-06T14:45:31.055Z","avatar_url":"https://github.com/kvs-coder.png","language":"Swift","funding_links":["https://github.com/sponsors/VictorKachalov"],"categories":[],"sub_categories":[],"readme":"# HealthKitReporter\n\n## About\n\nA wrapper above HealthKit Apple's framework for data manipulations.\nThe library supports manipulating with values from HealthKit repository and translating them to \u003ci\u003eCodable\u003c/i\u003e models allowing to encode the result as a simple JSON payload.\nIn addition you can write your own HealthKit objects using \u003ci\u003eCodable\u003c/i\u003e wrappers which will be translated to \u003ci\u003eHKObjectType\u003c/i\u003e objects inside HealthKit repository.\n\n## Start\n\n### Preparation\n\nAt first in your app's entitlements select HealthKit.\nIf you want to read Clinical Records then also check \"Clinical Health Records\" under Health Kit.\n***NOTE:*** *You can only tick the \"Clinical Health Records\" checkmark if your development team has a paid Apple developer subscription. To test on a real device, or to publish your application, you will need a paid Apple subscription, but you can still test on the iOS simulator without a subscription by setting the Development Team to None.*\n\nThen in your app's info.plist file add permissions:\n\n```xml\n\u003ckey\u003eNSHealthShareUsageDescription\u003c/key\u003e\n\u003cstring\u003eWHY_YOU_NEED_TO_SHARE_DATA\u003c/string\u003e\n\u003ckey\u003eNSHealthUpdateUsageDescription\u003c/key\u003e\n\u003cstring\u003eWHY_YOU_NEED_TO_USE_DATA\u003c/string\u003e\n```\n\nIf you plan to use **WorkoutRoute** **Series** please provide additionally CoreLocation permissions:\n\n```xml\n\u003ckey\u003eNSLocationAlwaysAndWhenInUseUsageDescription\u003c/key\u003e\n\u003cstring\u003eWHY_YOU_NEED_TO_ALWAYS_SHARE_LOCATION\u003c/string\u003e\n\u003ckey\u003eNSLocationWhenInUseUsageDescription\u003c/key\u003e\n\u003cstring\u003eWHY_YOU_NEED_TO_SHARE_LOCATION\u003c/string\u003e\n```\n\nIf you plan to read **Clinical Records** please provide additionally:\n\n```xml\n\u003ckey\u003eNSHealthClinicalHealthRecordsShareUsageDescription\u003c/key\u003e\n\u003cstring\u003eWHY_YOU_NEED_TO_SHARE_DATA\u003c/string\u003e\n```\n\n\n### Common usage\n\nYou create a \u003ci\u003eHealthKitReporter\u003c/i\u003e instance surrounded by do catch block. If Apple Health is not supported by the device (i.e. iPad) the catch block will be called.\n\nThe reporter instance contains several properties:\n* reader\n* writer\n* manager\n* observer\n\nEvery property is responsible for an appropriate part of HealthKit framework. Based from the naming, reader will handle every manipulation regarding reading data and writer will handle everything related to writing data in HealthKit repository, observer will handle observations and will notify if anything was changes in HealthKit, manager is responsible for the authorization of read/write types and launching a WatchApp you make.\n\nIf you want to read, write data or observe data changes, you always need to be sure that the data types are authorized to be read/written/observed. In that case manager has authorization method with completion block telling about the presentation of the authorization window. Notice that Apple Health Kit will show this window only once during the whole time app is installed on the device, in this case if some types were denied to be read or written, user should manually allow this in Apple Health App.\n\nIn examples below every operation is hapenning iside authorization block. It is recommended to do so, because if new type will be added, there will be thrown a permission exception. If you are sure that no new types will appear, you can call operations outside authorization block in your app, only if the type's data reading/writing permissions were granted.\n\n### Reading Data\nCreate a \u003ci\u003eHealthKitReporter\u003c/i\u003e instance.\n\nAuthorize desired types to read, like step count.\n\nIf authorization was successfull (the authorization window was shown) call sample query with type step count to create a **Query** object.\n\nUse reporter's **manager's** _executeQuery_ to execute the query. (Or _stopQuery_ to stop)\n\n```swift\ndo {\n    let reporter = try HealthKitReporter()\n    let types = [QuantityType.stepCount]\n    reporter.manager.requestAuthorization(\n        toRead: types,\n        toWrite: types\n    ) { (success, error) in\n        if success \u0026\u0026 error == nil {\n            reporter.manager.preferredUnits(for: types) { (preferredUnits, error) in\n                if error == nil {\n                    for preferredUnit in preferredUnits {\n                        do {\n                            let query = try reporter.reader.quantityQuery(\n                                type: try QuantityType.make(from: preferredUnit.identifier),\n                                unit: preferredUnit.unit\n                            ) { (results, error) in\n                                if error == nil {\n                                    for element in results {\n                                        do {\n                                            print(try element.encoded())\n                                        } catch {\n                                            print(error)\n                                        }\n                                    }\n                                } else {\n                                    print(error)\n                                }\n                            }\n                            reporter.manager.executeQuery(query)\n                        } catch {\n                            print(error)\n                        }\n                    }\n                } else {\n                    print(error)\n                }\n            }\n        } else {\n            print(error)\n        }\n    }\n} catch {\n    print(error)\n}\n```\n\nHere is a sample response for steps:\n\n```json\n\n{\n  \"sourceRevision\" : {\n    \"productType\" : \"iPhone8,1\",\n    \"systemVersion\" : \"14.0.0\",\n    \"source\" : {\n      \"name\" : \"Guy’s iPhone\",\n      \"bundleIdentifier\" : \"com.apple.health.47609E07-490D-4E5F-8E68-9D8904E9BA08\"\n    },\n    \"version\" : \"14.0\"\n  },\n  \"harmonized\" : {\n    \"value\" : 298,\n    \"unit\" : \"count\"\n  },\n  \"device\" : {\n    \"softwareVersion\" : \"14.0\",\n    \"manufacturer\" : \"Apple Inc.\",\n    \"model\" : \"iPhone\",\n    \"name\" : \"iPhone\",\n    \"hardwareVersion\" : \"iPhone8,1\"\n  },\n  \"endTimestamp\" : 1601066077.5886581,\n  \"identifier\" : \"HKQuantityTypeIdentifierStepCount\",\n  \"startTimestamp\" : 1601065755.8829093\n}\n```\n\n### Writing Data\n\n***NOTE:*** *Clinical Records are read only, Health Kit does not allow writing any data to Clinical Records.*\n\nCreate a \u003ci\u003eHealthKitReporter\u003c/i\u003e instance.\n\nAuthorize desired types to write, like step count.\n\nYou may call manager's \u003ci\u003epreferredUnits(for: )\u003c/i\u003e function to pass units (for \u003cb\u003eQuantity Types\u003c/b\u003e).\n\nIf authorization was successfull (the authorization window was shown) call save method with type step count.\n\n```swift\ndo {\n    let reporter = try HealthKitReporter()\n    let types = [QuantityType.stepCount]\n    reporter.manager.requestAuthorization(\n        toRead: types,\n        toWrite: types\n    ) { (success, error) in\n        if success \u0026\u0026 error == nil {\n            reporter.manager.preferredUnits(for: types) { (preferredUnits, error) in\n                for preferredUnit in preferredUnits {\n                    //Do write steps\n                    let identifier = preferredUnit.identifier\n                    guard\n                        identifier == QuantityType.stepCount.identifier\n                    else {\n                        return\n                    }\n                    let now = Date()\n                    let quantity = Quantity(\n                        identifier: identifier,\n                        startTimestamp: now.addingTimeInterval(-60).timeIntervalSince1970,\n                        endTimestamp: now.timeIntervalSince1970,\n                        device: Device(\n                            name: \"Guy's iPhone\",\n                            manufacturer: \"Guy\",\n                            model: \"6.1.1\",\n                            hardwareVersion: \"some_0\",\n                            firmwareVersion: \"some_1\",\n                            softwareVersion: \"some_2\",\n                            localIdentifier: \"some_3\",\n                            udiDeviceIdentifier: \"some_4\"\n                        ),\n                        sourceRevision: SourceRevision(\n                            source: Source(\n                                name: \"mySource\",\n                                bundleIdentifier: \"com.kvs.hkreporter\"\n                            ),\n                            version: \"1.0.0\",\n                            productType: \"CocoaPod\",\n                            systemVersion: \"1.0.0.0\",\n                            operatingSystem: SourceRevision.OperatingSystem(\n                                majorVersion: 1,\n                                minorVersion: 1,\n                                patchVersion: 1\n                            )\n                        ),\n                        harmonized: Quantity.Harmonized(\n                            value: 123.0,\n                            unit: preferredUnit.unit,\n                            metadata: nil\n                        )\n                    )\n                    reporter.writer.save(sample: quantity) { (success, error) in\n                        if success \u0026\u0026 error == nil {\n                            print(\"success\")\n                        } else {\n                            print(error)\n                        }\n                    }\n                }\n            }\n        } else {\n            print(error)\n        }\n    }\n} catch {\n    print(error)\n}\n```\n\nHint: if you have trouble with choosing unit for an object you want to save, you can call a manager's function _preferredUnits_ which will return a dictionary with keys as identifiers of Quantitiy types and Units preferred for current localization.\n\n```swift\nreporter.manager.preferredUnits(for: [.stepCount]) { (dictionary, error) in\n    for (identifier, unit) in dictionary {\n        print(\"\\(identifier) - \\(unit)\")\n    }\n}\n```\n\n## Observing Data\n\nCreate a \u003ci\u003eHealthKitReporter\u003c/i\u003e instance.\n\nAuthorize desired types to read/write, like step count and sleep analysis.\n\nYou might create an App which will be called every time by HealthKit, and receive notifications, that some data was changed in HealthKit depending on frequency. But keep in mind that sometimes the desired frequency you set cannot be fulfilled by HealthKit.\n\nCall the observation query method inside your AppDelegate's method. This will let Apple Health to send events even if the app is in background or wake up your app,  if it was previosly put into \"Not Running\" state and execute the code provided inside **observerQuery** update handler.\n\nWarning: to run **observerQuery** when the app is killed by the system, provide an additional capability **Background Mode** and select **Background fetch**\n\nUse reporter's **manager's** _executeQuery_ to execute the query. (Or _stopQuery_ to stop)\n\n```swift\nfunc application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n) -\u003e Bool {\n    do {\n        let reporter = try HealthKitReporter()\n        let types: [SampleType] = [\n            QuantityType.stepCount,\n            CategoryType.sleepAnalysis\n        ]\n        reporter.manager.requestAuthorization(\n            toRead: types,\n            toWrite: types\n        ) { (success, error) in\n            if success \u0026\u0026 error == nil {\n                for type in types {\n                    do {\n                        let query = try reporter.observer.observerQuery(\n                            type: type\n                        ) { (query, identifier, error) in\n                            if error == nil \u0026\u0026 identifier != nil {\n                                print(\"updates for \\(identifier!)\")\n                            }\n                        }\n                        reporter.observer.enableBackgroundDelivery(\n                            type: type,\n                            frequency: .daily\n                        ) { (success, error) in\n                            if error == nil {\n                                print(\"enabled\")\n                            }\n                        }\n                        reporter.manager.executeQuery(query)\n                    } catch {\n                        print(error)\n                    }\n                }\n            }\n        }\n    } catch {\n        print(error)\n    }\n    return true\n}\n```\n\n## Example\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n## Requirements\n\nThe library supports iOS 9 \u0026 above. \nSome features like HKHeartbeatSeries are available only starting with iOS 13.0 and like HKElectrocardiogramm starting with iOS 14.0\n\n## Installation\n\n### Cocoapods\n\nHealthKitReporter is available through [CocoaPods](https://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'HealthKitReporter'\n```\n\nor \n\n```ruby\npod 'HealthKitReporter', '~\u003e 3.1.0'\n```\n\n### Swift Package Manager\n\nTo install it, simply add the following lines to your Package.swift file\n(or just use the Package Manager from within XCode and reference this repo):\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/VictorKachalov/HealthKitReporter.git\", from: \"3.1.0\")\n]\n```\n\n### Carthage\n\nAdd the line in your cartfile \n\n```ruby\ngithub \"VictorKachalov/HealthKitReporter\" \"3.1.0\"\n```\n\n## Author\n\nVictor Kachalov, victorkachalov@gmail.com\n\n## License\n\nHealthKitReporter is available under the MIT license. See the LICENSE file for more info.\n\n## Sponsorhip\nIf you think that my repo helped you to solve the issues you struggle with, please don't be shy and sponsor :-)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkvs-coder%2Fhealthkitreporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkvs-coder%2Fhealthkitreporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkvs-coder%2Fhealthkitreporter/lists"}