├── .gitignore
├── screenshot
├── off.png
├── on.png
├── func1.png
├── func2.png
└── cocoapods.png
├── skoal-example
├── skoal-example
│ ├── skoal-example-Bridging-Header.h
│ ├── skoal-example.entitlements
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ └── ViewController.swift
├── skoal-example.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── BANYAN.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcuserdata
│ │ └── BANYAN.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.pbxproj
├── skoal-exampleTests
│ ├── Info.plist
│ └── skoal_exampleTests.swift
└── skoal-exampleUITests
│ ├── Info.plist
│ └── skoal_exampleUITests.swift
├── LICENSE
├── README.md
└── skoal
├── skoal.h
└── skoal.m
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 | skoal/.DS_Store
4 |
5 | .swift-version
6 |
--------------------------------------------------------------------------------
/screenshot/off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/screenshot/off.png
--------------------------------------------------------------------------------
/screenshot/on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/screenshot/on.png
--------------------------------------------------------------------------------
/screenshot/func1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/screenshot/func1.png
--------------------------------------------------------------------------------
/screenshot/func2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/screenshot/func2.png
--------------------------------------------------------------------------------
/screenshot/cocoapods.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/screenshot/cocoapods.png
--------------------------------------------------------------------------------
/skoal-example/skoal-example/skoal-example-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "skoal.h"
6 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example.xcodeproj/project.xcworkspace/xcuserdata/BANYAN.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apdevzhang/HealthKitUsageDemo/HEAD/skoal-example/skoal-example.xcodeproj/project.xcworkspace/xcuserdata/BANYAN.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/skoal-example/skoal-example/skoal-example.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.healthkit
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example.xcodeproj/xcuserdata/BANYAN.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | skoal-example.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/skoal-example/skoal-exampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/skoal-example/skoal-exampleUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 BANYAN
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/skoal-example/skoal-exampleTests/skoal_exampleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // skoal_exampleTests.swift
3 | // skoal-exampleTests
4 | //
5 | // Created by BANYAN on 2017/11/17.
6 | // Copyright © 2017年 skoal. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import skoal_example
11 |
12 | class skoal_exampleTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/skoal-example/skoal-exampleUITests/skoal_exampleUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // skoal_exampleUITests.swift
3 | // skoal-exampleUITests
4 | //
5 | // Created by BANYAN on 2017/11/17.
6 | // Copyright © 2017年 skoal. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class skoal_exampleUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSHealthShareUsageDescription
24 |
25 | NSHealthUpdateUsageDescription
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/skoal-example/skoal-example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // skoal-example
4 | //
5 | // Created by BANYAN on 2017/11/17.
6 | // Copyright © 2017年 skoal. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # skoal
2 | 
3 | 
4 | 
5 | 
6 | 
7 | 
8 |
9 | ## Skoal is a healthkit based library that supports reading and writing healthstore properties
10 |
11 | ## Supported Properties
12 | | Sample | HealthKit Identifier Type | Read | Write |
13 | |--------------|-----------------------------|----------|-----------|
14 | | StepCount | HKQuantityTypeIdentifierStepCount | ✓ | ✓ |
15 | | Height | HKQuantityTypeIdentifierHeight | ✓ | ✓ |
16 | | BodyMass | HKQuantityTypeIdentifierBodyMass | ✓ | ✓ ||
17 | | BodyMassIndex | HKQuantityTypeIdentifierBodyMassIndex | ✓ | ✓ |
18 | | DistanceWalkingRunning | HKQuantityTypeIdentifierDistanceWalkingRunning | ✓ | ✓ |
19 | | FlightsClimbed | HKQuantityTypeIdentifierFlightsClimbed | ✓ | ✓ |
20 | | RespiratoryRate | HKQuantityTypeIdentifierRespiratoryRate | ✓ | ✓ |
21 | | DietaryEnergyConsumed | HKQuantityTypeIdentifierDietaryEnergyConsumed | ✓ | ✓ |
22 | | OxygenSaturation | HKQuantityTypeIdentifierOxygenSaturation | ✓ | |
23 | | BodyTemperature | HKQuantityTypeIdentifierBodyTemperature | ✓ | ✓ |
24 | | BloodGlucose | HKQuantityTypeIdentifierBloodGlucose | ✓ | ✓ |
25 | | BloodPressureSystolic | HKQuantityTypeIdentifierBloodPressureSystolic | ✓ | ✓ |
26 | | BloodPressureDiastolic | HKQuantityTypeIdentifierBloodPressureDiastolic | ✓ | ✓ |
27 | | StandHour | HKCategoryTypeIdentifierAppleStandHour | ✓ | |
28 | | BiologicalSex | biologicalSexWithError | ✓ | |
29 | | DateOfBirth | dateOfBirthComponentsWithError | ✓ | |
30 | | BloodType | bloodTypeWithError | ✓ | |
31 | | FitzpatrickSkin | fitzpatrickSkinTypeWithError | ✓ | |
32 | | SleepAnalysis | HKCategoryTypeIdentifierSleepAnalysis | ✓ | |
33 | | MenstrualFlow | HKCategoryTypeIdentifierMenstrualFlow | ✓ | |
34 | | IntermenstrualBleeding | HKCategoryTypeIdentifierIntermenstrualBleeding | ✓ | |
35 | | SexualActivity | HKCategoryTypeIdentifierSexualActivity | ✓ | |
36 |
37 | ## License
38 | `skoal`use [__MIT license__][1]
39 |
40 | ## Usage
41 | - [You should get HealthKit privacy permission before you use 'skoal'](#index1)
42 | - [See the function by preview below](#index2)
43 | - [Start the project to see the example](./skoal-example)
44 |
45 |
46 | - Objective-C
47 | ```
48 | [[skoal sharedInstance]requestHealthPermissionWithBlock:^(HealthStorePermissionResponse permissionResponse) {
49 | if (permissionResponse == HealthStorePermissionResponseError) {
50 | DLog(@"请求权限失败");
51 | }else{
52 | DLog(@"请求权限成功");
53 | }
54 | }];
55 | ```
56 | - Swift
57 | ```
58 | skoal.sharedInstance().requestHealthPermission { (response: HealthStorePermissionResponse) in
59 | if response == HealthStorePermissionResponse.error {
60 | print("请求失败")
61 | } else {
62 | print("请求成功")
63 | }
64 | }
65 | ```
66 |
67 |
68 | func preview1 | func preview2
69 | ---------------|---------------
70 |  | 
71 |
72 |
73 | [1]: https://github.com/GREENBANYAN/skoal/blob/master/LICENSE "MIT License"
74 |
--------------------------------------------------------------------------------
/skoal/skoal.h:
--------------------------------------------------------------------------------
1 | // skoal.h
2 | //
3 | // Copyright (c) 2017 BANYAN
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in
13 | // all copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | // THE SOFTWARE.
22 |
23 | #import
24 | #import
25 | #import
26 |
27 | ///-------------------------
28 | #pragma mark - DEBUG
29 | ///-------------------------
30 | #ifdef DEBUG
31 | #define DLog(FORMAT, ...) fprintf(stderr, "%s [Line %zd]\t%s\n", [[[NSString stringWithUTF8String: __FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat: FORMAT, ## __VA_ARGS__] UTF8String]);
32 | #else
33 | #define DLog(FORMAT, ...) nil
34 | #endif
35 |
36 |
37 | typedef NS_ENUM(NSUInteger,HealthStorePermissionResponse) {
38 | HealthStorePermissionResponseError = 0,
39 | HealthStorePermissionResponseSuccess
40 | };
41 |
42 | typedef void (^HealthStorePermissionResponseBlock)(HealthStorePermissionResponse permissionResponse);
43 |
44 | @interface skoal : NSObject
45 | @property (nonatomic,copy) HealthStorePermissionResponseBlock permissionResponseBlock;
46 | @property (nonatomic,strong) HKHealthStore *store;
47 |
48 | +(instancetype)sharedInstance;
49 |
50 | ///-------------------------
51 | #pragma mark - AccessPermission(获取权限)
52 | ///-------------------------
53 | -(void)requestHealthPermissionWithBlock:(HealthStorePermissionResponseBlock)block;
54 |
55 |
56 | ///-------------------------
57 | #pragma mark - StepCount(步数)
58 | ///-------------------------
59 | -(void)readStepCountFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
60 | -(void)readStepCountFromHealthStoreWithStartTime:(NSString *)startTime endTime:(NSString *)endTime completion:(void(^)(double value,NSError *error))completion;
61 | -(void)writeStepCountToHealthStoreWithUnit:(double)setpCount completion:(void(^)(BOOL response))completion;
62 | -(void)writeStepCountToHealthStoreWithUnit:(double)setpCount startTime:(NSString *)startTime endTime:(NSString *)endTime completion:(void(^)(BOOL response))completion;
63 |
64 |
65 | ///-------------------------
66 | #pragma mark - Height(身高)
67 | ///-------------------------
68 | -(void)readHeightFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
69 | -(void)writeHeightToHealthStoreWithUnit:(double)Height completion:(void(^)(BOOL response))completion;
70 |
71 |
72 | ///-------------------------
73 | #pragma mark - BodyMass(体重)
74 | ///-------------------------
75 | -(void)readBodyMassFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion; /// kg
76 | -(void)writeBodyMassToHealthStoreWithUnit:(double)bodyMass completion:(void(^)(BOOL response))completion;
77 |
78 |
79 | ///-------------------------
80 | #pragma mark - BodyMassIndex(身体质量指数)
81 | ///-------------------------
82 | -(void)readBodyMassIndexFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
83 | -(void)writeBodyMassIndexToHealthStoreWithUnit:(double)bodyMassIndex completion:(void(^)(BOOL response))completion;
84 |
85 |
86 | ///-------------------------
87 | #pragma mark - DistanceWalkingRunning(步行+跑步距离)
88 | ///-------------------------
89 | -(void)readDistanceWalkingRunningFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
90 | -(void)writeDistanceWalkingRunningToHealthStoreWithUnit:(double)distanceWalkingRunning completion:(void(^)(BOOL response))completion;
91 |
92 |
93 | ///-------------------------
94 | #pragma mark - FlightsClimbed(以爬楼层)
95 | ///-------------------------
96 | -(void)readFlightsClimbedFromHealthStoreWithCompletion:(void(^)(NSInteger value,NSError *error))completion;
97 | -(void)writeFlightsClimbedToHealthStoreWithUnit:(NSInteger)flightsClimbed completion:(void(^)(BOOL response))completion;
98 |
99 |
100 | ///-------------------------
101 | #pragma mark - RespiratoryRate(呼吸速率)
102 | ///-------------------------
103 | -(void)readRespiratoryRateFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
104 | -(void)writeRespiratoryRateToHealthStoreWithUnit:(double)respiratoryRate completion:(void(^)(BOOL response))completion;
105 |
106 |
107 | ///-------------------------
108 | #pragma mark - DietaryEnergyConsumed(膳食能量消耗)
109 | ///-------------------------
110 | -(void)readDietaryEnergyConsumedFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
111 | -(void)writeDietaryEnergyConsumedToHealthStoreWithUnit:(double)dietaryEnergyConsumed completion:(void(^)(BOOL response))completion;
112 |
113 |
114 | ///-------------------------
115 | #pragma mark - OxygenSaturation(血氧饱和度)
116 | ///-------------------------
117 | -(void)readOxygenSaturationFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
118 |
119 |
120 | ///-------------------------
121 | #pragma mark - BodyTemperature(体温)
122 | ///-------------------------
123 | -(void)readBodyTemperatureFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
124 | -(void)writeBodyTemperatureToHealthStoreWithUnit:(double)bodyTemperature completion:(void(^)(BOOL response))completion;
125 |
126 |
127 | ///-------------------------
128 | #pragma mark - BloodGlucose(血糖)
129 | ///-------------------------
130 | -(void)readBloodGlucoseFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion; /// mg/dl
131 | -(void)writeBloodGlucoseToHealthStoreWithUnit:(double)bloodGlucose completion:(void(^)(BOOL response))completion;
132 |
133 | ///-------------------------
134 | #pragma mark - BloodPressure(血压)
135 | ///-------------------------
136 | -(void)readBloodPressureSystolicFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
137 | -(void)writeBloodPressureSystolicToHealthStoreWithUnit:(double)bloodPressureSystolic completion:(void(^)(BOOL response))completion;
138 | -(void)readBloodPressureDiastolicFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
139 | -(void)writeBloodPressureDiastolicToHealthStoreWithUnit:(double)bloodPressureDiastolic completion:(void(^)(BOOL response))completion;
140 |
141 |
142 | ///-------------------------
143 | #pragma mark - StandHour(站立小时)
144 | ///-------------------------
145 | -(void)readStandHourFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
146 |
147 |
148 | ///-------------------------
149 | #pragma mark - BiologicalSex(性别)
150 | ///-------------------------
151 | -(void)readBiologicalSexFromHealthStoreWithCompletion:(void(^)(NSString *sex,NSError *error))completion;
152 |
153 |
154 | ///-------------------------
155 | #pragma mark - DateOfBirth(出生日期)
156 | ///-------------------------
157 | -(void)readDateOfBirthFromHealthStoreWithCompletion:(void(^)(NSDate *date,NSError *error))completion;
158 |
159 |
160 | ///-------------------------
161 | #pragma mark - BloodType(血型)
162 | ///-------------------------
163 | -(void)readBloodTypeFromHealthStoreWithCompletion:(void(^)(NSString *bloodType,NSError *error))completion;
164 |
165 |
166 | ///-------------------------
167 | #pragma mark - FitzpatrickSkin(日光反应型皮肤类型)
168 | ///-------------------------
169 | -(void)readFitzpatrickSkinFromHealthStoreWithCompletion:(void(^)(NSString *skinType,NSError *error))completion;
170 |
171 |
172 | ///-------------------------
173 | #pragma mark - SleepAnalysis(睡眠分析)
174 | ///-------------------------
175 | -(void)readSleepAnalysisFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
176 |
177 |
178 | ///-------------------------
179 | #pragma mark - MenstrualFlow(月经)
180 | ///-------------------------
181 | -(void)readMenstrualFlowFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
182 |
183 |
184 | ///-------------------------
185 | #pragma mark - IntermenstrualBleeding(点滴出血)
186 | ///-------------------------
187 | -(void)readIntermenstrualBleedingFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
188 |
189 |
190 | ///-------------------------
191 | #pragma mark - SexualActivity(性行为)
192 | ///-------------------------
193 | -(void)readSexualActivityFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
194 |
195 |
196 | @end
197 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // skoal-example
4 | //
5 | // Created by BANYAN on 2017/11/17.
6 | // Copyright © 2017年 skoal. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
12 |
13 | let permission: [String] = ["请求权限"]
14 | let setpCount: [String] = ["读取当天总步数","读取一定时间段内的步数","写入当天总步数","写入一定时间段的步数"]
15 | let height: [String] = ["读取身高","写入身高"]
16 | let bodyMass: [String] = ["读取体重","写入体重"]
17 | let bodyMassIndex: [String] = ["读取身体质量指数","写入身体质量指数"]
18 | let distanceWalkingRunning: [String] = ["读取步行加跑步距离","写入步行加跑步距离"]
19 | let flightsClimbed: [String] = ["读取当天以爬楼层","写入当天以爬楼层"]
20 | let respiratoryRate: [String] = ["读取呼吸速率","写入呼吸速率"]
21 | let dietaryEnergyConsumed: [String] = ["读取膳食能量消耗","写入膳食能量消耗"]
22 | let oxygenSaturation: [String] = ["血氧饱和度"]
23 | let bodyTemperature: [String] = ["读取体温","写入体温"]
24 | let bloodGlucose: [String] = ["读取血糖","写入血糖"]
25 | let bloodPressure: [String] = ["读取血压收缩压","写入血压收缩压","读取血压舒张压","写入血压舒张压"]
26 | let standHour: [String] = ["读取当天站立小时"]
27 | let biologicalSex: [String] = ["读取性别"]
28 | let dateOfBirth: [String] = ["读取出生日期"]
29 | let bloodType: [String] = ["读取血型"]
30 | let fitzpatrickSkin: [String] = ["日光反应型皮肤类型"]
31 | let sleepAnalysis: [String] = ["读取睡眠分析"]
32 | let menstrualFlow: [String] = ["读取最近一次月经"]
33 | let intermenstrualBleeding: [String] = ["读取点滴出血"]
34 | let sexualActivity: [String] = ["读取最近一次性行为"]
35 |
36 | var alertText: String = String()
37 |
38 | var _tableView: UITableView!
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 |
43 | self.view.backgroundColor = UIColor.white
44 |
45 | initUI()
46 | }
47 |
48 |
49 | ///-------------------------
50 | /// Objective-C请求权限示例
51 | ///-------------------------
52 | // [[skoal sharedInstance]requestHealthPermissionWithBlock:^(HealthStorePermissionResponse permissionResponse) {
53 | // if (permissionResponse == HealthStorePermissionResponseError) {
54 | // DLog(@"请求权限失败");
55 | // }else{
56 | // DLog(@"请求权限成功");
57 | // }
58 | // }];
59 |
60 | //MARK:UI
61 | func initUI() {
62 | _tableView = UITableView.init(frame:CGRect.init(x:0,y:0,width:self.view.frame.size.width,height:self.view.frame.size.height),style:UITableViewStyle.plain)
63 | _tableView.delegate = self
64 | _tableView.dataSource = self
65 | _tableView.showsVerticalScrollIndicator = false
66 | _tableView.tableFooterView = UIView.init()
67 | self.view.addSubview(_tableView)
68 | _tableView.register(UITableViewCell().classForCoder, forCellReuseIdentifier: "cellId")
69 | }
70 |
71 | //MARK:UITbleviewDelegate,UITableViewDataSource
72 | func numberOfSections(in tableView: UITableView) -> Int {
73 | return 22
74 | }
75 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
76 | switch section {
77 | case 0:
78 | return 1
79 | case 1:
80 | return 4
81 | case 2:
82 | return 2
83 | case 3:
84 | return 2
85 | case 4:
86 | return 2
87 | case 5:
88 | return 2
89 | case 6:
90 | return 2
91 | case 7:
92 | return 2
93 | case 8:
94 | return 2
95 | case 9:
96 | return 1
97 | case 10:
98 | return 2
99 | case 11:
100 | return 2
101 | case 12:
102 | return 4
103 | case 13:
104 | return 1
105 | case 14:
106 | return 1
107 | case 15:
108 | return 1
109 | case 16:
110 | return 1
111 | case 17:
112 | return 1
113 | case 18:
114 | return 1
115 | case 19:
116 | return 1
117 | case 20:
118 | return 1
119 | case 21:
120 | return 1
121 | default:
122 | return 0
123 | }
124 | }
125 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
126 | return 40
127 | }
128 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
129 | switch section {
130 | case 0:
131 | return "获取权限"
132 | case 1:
133 | return "步数"
134 | case 2:
135 | return "身高"
136 | case 3:
137 | return "体重"
138 | case 4:
139 | return "身体质量指数"
140 | case 5:
141 | return "步行+跑步距离"
142 | case 6:
143 | return "以爬楼层"
144 | case 7:
145 | return "呼吸速率"
146 | case 8:
147 | return "膳食能量消耗"
148 | case 9:
149 | return "血氧饱和度"
150 | case 10:
151 | return "体温"
152 | case 11:
153 | return "血糖"
154 | case 12:
155 | return "血压"
156 | case 13:
157 | return "站立小时"
158 | case 14:
159 | return "性别"
160 | case 15:
161 | return "出生日期"
162 | case 16:
163 | return "血型"
164 | case 17:
165 | return "日光反应型皮肤类型"
166 | case 18:
167 | return "睡眠分析"
168 | case 19:
169 | return "月经"
170 | case 20:
171 | return "点滴出血"
172 | case 21:
173 | return "性行为"
174 | default:
175 | return ""
176 | }
177 | }
178 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
179 | let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
180 |
181 | if indexPath.section == 0 {
182 | cell.textLabel!.text = permission[indexPath.row]
183 | } else if indexPath.section == 1 {
184 | cell.textLabel!.text = setpCount[indexPath.row]
185 | } else if indexPath.section == 2 {
186 | cell.textLabel!.text = height[indexPath.row]
187 | } else if indexPath.section == 3 {
188 | cell.textLabel!.text = bodyMass[indexPath.row]
189 | } else if indexPath.section == 4 {
190 | cell.textLabel!.text = bodyMassIndex[indexPath.row]
191 | } else if indexPath.section == 5 {
192 | cell.textLabel!.text = distanceWalkingRunning[indexPath.row]
193 | } else if indexPath.section == 6 {
194 | cell.textLabel!.text = flightsClimbed[indexPath.row]
195 | } else if indexPath.section == 7 {
196 | cell.textLabel!.text = respiratoryRate[indexPath.row]
197 | } else if indexPath.section == 8 {
198 | cell.textLabel!.text = dietaryEnergyConsumed[indexPath.row]
199 | } else if indexPath.section == 9 {
200 | cell.textLabel!.text = oxygenSaturation[indexPath.row]
201 | } else if indexPath.section == 10 {
202 | cell.textLabel!.text = bodyTemperature[indexPath.row]
203 | } else if indexPath.section == 11 {
204 | cell.textLabel!.text = bloodGlucose[indexPath.row]
205 | } else if indexPath.section == 12 {
206 | cell.textLabel!.text = bloodPressure[indexPath.row]
207 | } else if indexPath.section == 13 {
208 | cell.textLabel!.text = standHour[indexPath.row]
209 | } else if indexPath.section == 14 {
210 | cell.textLabel!.text = biologicalSex[indexPath.row]
211 | } else if indexPath.section == 15 {
212 | cell.textLabel!.text = dateOfBirth[indexPath.row]
213 | } else if indexPath.section == 16 {
214 | cell.textLabel!.text = bloodType[indexPath.row]
215 | } else if indexPath.section == 17 {
216 | cell.textLabel!.text = fitzpatrickSkin[indexPath.row]
217 | } else if indexPath.section == 18 {
218 | cell.textLabel!.text = sleepAnalysis[indexPath.row]
219 | } else if indexPath.section == 19 {
220 | cell.textLabel!.text = menstrualFlow[indexPath.row]
221 | } else if indexPath.section == 20 {
222 | cell.textLabel!.text = intermenstrualBleeding[indexPath.row]
223 | } else if indexPath.section == 21 {
224 | cell.textLabel!.text = sexualActivity[indexPath.row]
225 | }
226 |
227 | cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 12)
228 | cell.textLabel?.textColor = UIColor.lightGray
229 | cell.selectionStyle = UITableViewCellSelectionStyle.default
230 | cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
231 |
232 | return cell
233 | }
234 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
235 | switch indexPath.section {
236 | case 0: // AccessPermission(获取权限)
237 | if indexPath.row == 0 {
238 | skoal.sharedInstance().requestHealthPermission { (response: HealthStorePermissionResponse) in
239 | if response == HealthStorePermissionResponse.error {
240 | print("请求失败")
241 | } else {
242 | print("请求成功")
243 | }
244 | }
245 | }
246 | case 1: // StepCount(步数)
247 | if indexPath.row == 0 {
248 | skoal.sharedInstance().readStepCountFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
249 | print("\(value)\n\(error.debugDescription)")
250 | })
251 | } else if indexPath.row == 1 {
252 | skoal.sharedInstance().readStepCountFromHealthStore(withStartTime: "2017-11-17 08:00", endTime: "2017-11-17 10:00", completion: { (_ value: Double, _ error: Error?) in
253 | print("\(value)\n\(error.debugDescription)")
254 | })
255 | } else if indexPath.row == 2 {
256 | skoal.sharedInstance().writeStepCountToHealthStore(withUnit: 888, completion: { (_ response: Bool) in
257 | print(response)
258 | })
259 | } else if indexPath.row == 3 {
260 | skoal.sharedInstance().writeStepCountToHealthStore(withUnit: 888, startTime: "2017-11-17 11:00", endTime: "2017-11-17 12:00", completion: { (_ response: Bool) in
261 | print(response)
262 | })
263 | }
264 | case 2: // Height(身高)
265 | if indexPath.row == 0 {
266 | skoal.sharedInstance().readHeightFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
267 | print("\(value)\n\(error.debugDescription)")
268 | })
269 | } else if indexPath.row == 1 {
270 | skoal.sharedInstance().writeHeightToHealthStore(withUnit: 1.80, completion: { (_ response: Bool) in
271 | print(response)
272 | })
273 | }
274 | case 3: // BodyMass(体重)
275 | if indexPath.row == 0 {
276 | skoal.sharedInstance().readBodyMassFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
277 | print("\(value)\n\(error.debugDescription)")
278 | })
279 | } else if indexPath.row == 1 {
280 | skoal.sharedInstance().writeBodyMassToHealthStore(withUnit: 70, completion: { (_ response: Bool) in
281 | print(response)
282 | })
283 | }
284 | case 4: // BodyMassIndex(身体质量指数)
285 | if indexPath.row == 0 {
286 | skoal.sharedInstance().readBodyMassIndexFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
287 | print("\(value)\n\(error.debugDescription)")
288 | })
289 | } else if indexPath.row == 1 {
290 | skoal.sharedInstance().writeBodyMassIndexToHealthStore(withUnit: 22, completion: { (_ response: Bool) in
291 | print(response)
292 | })
293 | }
294 | case 5: // DistanceWalkingRunning(步行+跑步距离)
295 | if indexPath.row == 0 {
296 | skoal.sharedInstance().readDistanceWalkingRunningFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
297 | print("\(value)\n\(error.debugDescription)")
298 | })
299 | } else if indexPath.row == 1 {
300 | skoal.sharedInstance().writeDistanceWalkingRunningToHealthStore(withUnit: 20.0, completion: { (_ response: Bool) in
301 | print(response)
302 | })
303 | }
304 | case 6: //FlightsClimbed(以爬楼层)
305 | if indexPath.row == 0 {
306 | skoal.sharedInstance().readFlightsClimbedFromHealthStore(completion: { (_ flightsClimbed: NSInteger, _ error: Error?) in
307 | print("\(flightsClimbed)\n\(error.debugDescription)")
308 | })
309 | } else if indexPath.row == 1 {
310 | skoal.sharedInstance().writeFlightsClimbedToHealthStore(withUnit: 23, completion: { (_ response: Bool) in
311 | print(response)
312 | })
313 | }
314 | case 7: // RespiratoryRate(呼吸速率)
315 | if indexPath.row == 0 {
316 | skoal.sharedInstance().readRespiratoryRateFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
317 | print("\(value)\n\(error.debugDescription)")
318 | })
319 | } else if indexPath.row == 1 {
320 | skoal.sharedInstance().writeRespiratoryRateToHealthStore(withUnit: 20.0, completion: { (_ response: Bool) in
321 | print(response)
322 | })
323 | }
324 | case 8: // DietaryEnergyConsumed(膳食能量消耗)
325 | if indexPath.row == 0 {
326 | skoal.sharedInstance().readDietaryEnergyConsumedFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
327 | print("\(value)\n\(error.debugDescription)")
328 | })
329 | } else if indexPath.row == 1 {
330 | skoal.sharedInstance().writeDietaryEnergyConsumedToHealthStore(withUnit: 22.2, completion: { (_ response: Bool) in
331 | print(response)
332 | })
333 | }
334 | case 9: // OxygenSaturation(血氧饱和度)
335 | if indexPath.row == 0 {
336 | skoal.sharedInstance().readOxygenSaturationFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
337 | print("\(value)\n\(error.debugDescription)")
338 | })
339 | }
340 | case 10: // BodyTemperature(体温)
341 | if indexPath.row == 0 {
342 | skoal.sharedInstance().readBodyTemperatureFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
343 | print("\(value)\n\(error.debugDescription)")
344 | })
345 | } else if indexPath.row == 1 {
346 | skoal.sharedInstance().writeBodyTemperatureToHealthStore(withUnit: 35.0, completion: { (_ response: Bool) in
347 | print(response)
348 | })
349 | }
350 | case 11: // BloodGlucose(血糖)
351 | if indexPath.row == 0 {
352 | skoal.sharedInstance().readBloodGlucoseFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
353 | print("\(value)\n\(error.debugDescription)")
354 | })
355 | } else if indexPath.row == 1 {
356 | skoal.sharedInstance().writeBloodGlucoseToHealthStore(withUnit: 16.0, completion: { (_ response: Bool) in
357 | print(response)
358 | })
359 | }
360 | case 12: // BloodPressure(血压)
361 | if indexPath.row == 0 {
362 | skoal.sharedInstance().readBloodPressureSystolicFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
363 | print("\(value)\n\(error.debugDescription)")
364 | })
365 | } else if indexPath.row == 1 {
366 | skoal.sharedInstance().writeBloodPressureSystolicToHealthStore(withUnit: 65.0, completion: { (_ response: Bool) in
367 | print(response)
368 | })
369 | } else if indexPath.row == 2 {
370 | skoal.sharedInstance().readBloodPressureDiastolicFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
371 | print("\(value)\n\(error.debugDescription)")
372 | })
373 | } else if indexPath.row == 3 {
374 | skoal.sharedInstance().writeBloodPressureDiastolicToHealthStore(withUnit: 77.0, completion: { (_ response: Bool) in
375 | print(response)
376 | })
377 | }
378 | case 13: // StandHour(站立小时)
379 | if indexPath.row == 0 {
380 | skoal.sharedInstance().readStandHourFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
381 | print("\(value)\n\(error.debugDescription)")
382 | })
383 | }
384 | case 14: // BiologicalSex(性别)
385 | if indexPath.row == 0 {
386 | skoal.sharedInstance().readBiologicalSexFromHealthStore(completion: { (_ biologicalSex: String!, _ error: Error?) in
387 | print("\(biologicalSex)\n\(error.debugDescription)")
388 | })
389 | }
390 | case 15: // DateOfBirth(出生日期)
391 | if indexPath.row == 0 {
392 | skoal.sharedInstance().readDateOfBirthFromHealthStore(completion: { (_ date: Date!, _ error: Error?) in
393 | print("\(date)\n\(error.debugDescription)")
394 | })
395 | }
396 | case 16: // BloodType(血型)
397 | if indexPath.row == 0 {
398 | skoal.sharedInstance().readBloodTypeFromHealthStore(completion: { (_ bloodType: String!, _ error: Error?) in
399 | print("\(bloodType)\n\(error.debugDescription)")
400 | })
401 | }
402 | case 17: // FitzpatrickSkin(日光反应型皮肤类型)
403 | if indexPath.row == 0 {
404 | skoal.sharedInstance().readFitzpatrickSkinFromHealthStore(completion: { (_ skinType: String!, _ error: Error?) in
405 | print("\(skinType)\n\(error.debugDescription)")
406 | })
407 | }
408 | case 18: // SleepAnalysis(睡眠分析)
409 | if indexPath.row == 0 {
410 | skoal.sharedInstance().readSleepAnalysisFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
411 | print("\(value)\n\(error.debugDescription)")
412 | })
413 | }
414 | case 19: // MenstrualFlow(月经)
415 | if indexPath.row == 0 {
416 | skoal.sharedInstance().readMenstrualFlowFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
417 | print("\(value)\n\(error.debugDescription)")
418 | })
419 | }
420 | case 20: // IntermenstrualBleeding(点滴出血)
421 | if indexPath.row == 0 {
422 | skoal.sharedInstance().readIntermenstrualBleedingFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
423 | print("\(value)\n\(error.debugDescription)")
424 | })
425 | }
426 | case 21: // SexualActivity(性行为)
427 | if indexPath.row == 0 {
428 | skoal.sharedInstance().readSexualActivityFromHealthStore(completion: { (_ value: Double, _ error: Error?) in
429 | print("\(value)\n\(error.debugDescription)")
430 | })
431 | }
432 | default:
433 | print("")
434 | }
435 | _tableView.reloadData()
436 | }
437 |
438 | override func didReceiveMemoryWarning() {
439 | super.didReceiveMemoryWarning()
440 | // Dispose of any resources that can be recreated.
441 | }
442 |
443 |
444 | }
445 |
446 |
--------------------------------------------------------------------------------
/skoal-example/skoal-example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 23DE147A1FBEB52A0010E36B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23DE14791FBEB52A0010E36B /* AppDelegate.swift */; };
11 | 23DE147F1FBEB52A0010E36B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23DE147D1FBEB52A0010E36B /* Main.storyboard */; };
12 | 23DE14811FBEB52B0010E36B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23DE14801FBEB52B0010E36B /* Assets.xcassets */; };
13 | 23DE14841FBEB52B0010E36B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23DE14821FBEB52B0010E36B /* LaunchScreen.storyboard */; };
14 | 23DE148F1FBEB52B0010E36B /* skoal_exampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23DE148E1FBEB52B0010E36B /* skoal_exampleTests.swift */; };
15 | 23DE149A1FBEB52B0010E36B /* skoal_exampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23DE14991FBEB52B0010E36B /* skoal_exampleUITests.swift */; };
16 | 23DE14AC1FBEB5580010E36B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23DE14AB1FBEB5580010E36B /* ViewController.swift */; };
17 | 23DE14B71FBEB5F70010E36B /* skoal.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DE14B61FBEB5F70010E36B /* skoal.m */; };
18 | 23DE14BD1FBEB6EA0010E36B /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DE14BC1FBEB6EA0010E36B /* HealthKit.framework */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 23DE148B1FBEB52B0010E36B /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 23DE146E1FBEB52A0010E36B /* Project object */;
25 | proxyType = 1;
26 | remoteGlobalIDString = 23DE14751FBEB52A0010E36B;
27 | remoteInfo = "skoal-example";
28 | };
29 | 23DE14961FBEB52B0010E36B /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 23DE146E1FBEB52A0010E36B /* Project object */;
32 | proxyType = 1;
33 | remoteGlobalIDString = 23DE14751FBEB52A0010E36B;
34 | remoteInfo = "skoal-example";
35 | };
36 | /* End PBXContainerItemProxy section */
37 |
38 | /* Begin PBXFileReference section */
39 | 23DE14761FBEB52A0010E36B /* skoal-example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "skoal-example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40 | 23DE14791FBEB52A0010E36B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
41 | 23DE147E1FBEB52A0010E36B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 23DE14801FBEB52B0010E36B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 23DE14831FBEB52B0010E36B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 23DE14851FBEB52B0010E36B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | 23DE148A1FBEB52B0010E36B /* skoal-exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "skoal-exampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 23DE148E1FBEB52B0010E36B /* skoal_exampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = skoal_exampleTests.swift; sourceTree = ""; };
47 | 23DE14901FBEB52B0010E36B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | 23DE14951FBEB52B0010E36B /* skoal-exampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "skoal-exampleUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 23DE14991FBEB52B0010E36B /* skoal_exampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = skoal_exampleUITests.swift; sourceTree = ""; };
50 | 23DE149B1FBEB52B0010E36B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
51 | 23DE14AB1FBEB5580010E36B /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
52 | 23DE14B01FBEB5EB0010E36B /* skoal-example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "skoal-example-Bridging-Header.h"; sourceTree = ""; };
53 | 23DE14B51FBEB5F70010E36B /* skoal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = skoal.h; sourceTree = ""; };
54 | 23DE14B61FBEB5F70010E36B /* skoal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = skoal.m; sourceTree = ""; };
55 | 23DE14BB1FBEB6C00010E36B /* skoal-example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "skoal-example.entitlements"; sourceTree = ""; };
56 | 23DE14BC1FBEB6EA0010E36B /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
57 | /* End PBXFileReference section */
58 |
59 | /* Begin PBXFrameworksBuildPhase section */
60 | 23DE14731FBEB52A0010E36B /* Frameworks */ = {
61 | isa = PBXFrameworksBuildPhase;
62 | buildActionMask = 2147483647;
63 | files = (
64 | 23DE14BD1FBEB6EA0010E36B /* HealthKit.framework in Frameworks */,
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | 23DE14871FBEB52B0010E36B /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 23DE14921FBEB52B0010E36B /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | );
80 | runOnlyForDeploymentPostprocessing = 0;
81 | };
82 | /* End PBXFrameworksBuildPhase section */
83 |
84 | /* Begin PBXGroup section */
85 | 23DE146D1FBEB52A0010E36B = {
86 | isa = PBXGroup;
87 | children = (
88 | 23DE14B41FBEB5F70010E36B /* skoal */,
89 | 23DE14781FBEB52A0010E36B /* skoal-example */,
90 | 23DE148D1FBEB52B0010E36B /* skoal-exampleTests */,
91 | 23DE14981FBEB52B0010E36B /* skoal-exampleUITests */,
92 | 23DE14771FBEB52A0010E36B /* Products */,
93 | 23DE14B81FBEB6C00010E36B /* Frameworks */,
94 | );
95 | sourceTree = "";
96 | };
97 | 23DE14771FBEB52A0010E36B /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 23DE14761FBEB52A0010E36B /* skoal-example.app */,
101 | 23DE148A1FBEB52B0010E36B /* skoal-exampleTests.xctest */,
102 | 23DE14951FBEB52B0010E36B /* skoal-exampleUITests.xctest */,
103 | );
104 | name = Products;
105 | sourceTree = "";
106 | };
107 | 23DE14781FBEB52A0010E36B /* skoal-example */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 23DE14BB1FBEB6C00010E36B /* skoal-example.entitlements */,
111 | 23DE14791FBEB52A0010E36B /* AppDelegate.swift */,
112 | 23DE14AB1FBEB5580010E36B /* ViewController.swift */,
113 | 23DE147D1FBEB52A0010E36B /* Main.storyboard */,
114 | 23DE14801FBEB52B0010E36B /* Assets.xcassets */,
115 | 23DE14821FBEB52B0010E36B /* LaunchScreen.storyboard */,
116 | 23DE14851FBEB52B0010E36B /* Info.plist */,
117 | 23DE14B01FBEB5EB0010E36B /* skoal-example-Bridging-Header.h */,
118 | );
119 | path = "skoal-example";
120 | sourceTree = "";
121 | };
122 | 23DE148D1FBEB52B0010E36B /* skoal-exampleTests */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 23DE148E1FBEB52B0010E36B /* skoal_exampleTests.swift */,
126 | 23DE14901FBEB52B0010E36B /* Info.plist */,
127 | );
128 | path = "skoal-exampleTests";
129 | sourceTree = "";
130 | };
131 | 23DE14981FBEB52B0010E36B /* skoal-exampleUITests */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 23DE14991FBEB52B0010E36B /* skoal_exampleUITests.swift */,
135 | 23DE149B1FBEB52B0010E36B /* Info.plist */,
136 | );
137 | path = "skoal-exampleUITests";
138 | sourceTree = "";
139 | };
140 | 23DE14B41FBEB5F70010E36B /* skoal */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 23DE14B51FBEB5F70010E36B /* skoal.h */,
144 | 23DE14B61FBEB5F70010E36B /* skoal.m */,
145 | );
146 | name = skoal;
147 | path = ../skoal;
148 | sourceTree = "";
149 | };
150 | 23DE14B81FBEB6C00010E36B /* Frameworks */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 23DE14BC1FBEB6EA0010E36B /* HealthKit.framework */,
154 | );
155 | name = Frameworks;
156 | sourceTree = "";
157 | };
158 | /* End PBXGroup section */
159 |
160 | /* Begin PBXNativeTarget section */
161 | 23DE14751FBEB52A0010E36B /* skoal-example */ = {
162 | isa = PBXNativeTarget;
163 | buildConfigurationList = 23DE149E1FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-example" */;
164 | buildPhases = (
165 | 23DE14721FBEB52A0010E36B /* Sources */,
166 | 23DE14731FBEB52A0010E36B /* Frameworks */,
167 | 23DE14741FBEB52A0010E36B /* Resources */,
168 | );
169 | buildRules = (
170 | );
171 | dependencies = (
172 | );
173 | name = "skoal-example";
174 | productName = "skoal-example";
175 | productReference = 23DE14761FBEB52A0010E36B /* skoal-example.app */;
176 | productType = "com.apple.product-type.application";
177 | };
178 | 23DE14891FBEB52B0010E36B /* skoal-exampleTests */ = {
179 | isa = PBXNativeTarget;
180 | buildConfigurationList = 23DE14A11FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-exampleTests" */;
181 | buildPhases = (
182 | 23DE14861FBEB52B0010E36B /* Sources */,
183 | 23DE14871FBEB52B0010E36B /* Frameworks */,
184 | 23DE14881FBEB52B0010E36B /* Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | 23DE148C1FBEB52B0010E36B /* PBXTargetDependency */,
190 | );
191 | name = "skoal-exampleTests";
192 | productName = "skoal-exampleTests";
193 | productReference = 23DE148A1FBEB52B0010E36B /* skoal-exampleTests.xctest */;
194 | productType = "com.apple.product-type.bundle.unit-test";
195 | };
196 | 23DE14941FBEB52B0010E36B /* skoal-exampleUITests */ = {
197 | isa = PBXNativeTarget;
198 | buildConfigurationList = 23DE14A41FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-exampleUITests" */;
199 | buildPhases = (
200 | 23DE14911FBEB52B0010E36B /* Sources */,
201 | 23DE14921FBEB52B0010E36B /* Frameworks */,
202 | 23DE14931FBEB52B0010E36B /* Resources */,
203 | );
204 | buildRules = (
205 | );
206 | dependencies = (
207 | 23DE14971FBEB52B0010E36B /* PBXTargetDependency */,
208 | );
209 | name = "skoal-exampleUITests";
210 | productName = "skoal-exampleUITests";
211 | productReference = 23DE14951FBEB52B0010E36B /* skoal-exampleUITests.xctest */;
212 | productType = "com.apple.product-type.bundle.ui-testing";
213 | };
214 | /* End PBXNativeTarget section */
215 |
216 | /* Begin PBXProject section */
217 | 23DE146E1FBEB52A0010E36B /* Project object */ = {
218 | isa = PBXProject;
219 | attributes = {
220 | LastSwiftUpdateCheck = 0910;
221 | LastUpgradeCheck = 0910;
222 | ORGANIZATIONNAME = skoal;
223 | TargetAttributes = {
224 | 23DE14751FBEB52A0010E36B = {
225 | CreatedOnToolsVersion = 9.1;
226 | LastSwiftMigration = 0910;
227 | ProvisioningStyle = Automatic;
228 | SystemCapabilities = {
229 | com.apple.HealthKit = {
230 | enabled = 1;
231 | };
232 | };
233 | };
234 | 23DE14891FBEB52B0010E36B = {
235 | CreatedOnToolsVersion = 9.1;
236 | ProvisioningStyle = Automatic;
237 | TestTargetID = 23DE14751FBEB52A0010E36B;
238 | };
239 | 23DE14941FBEB52B0010E36B = {
240 | CreatedOnToolsVersion = 9.1;
241 | ProvisioningStyle = Automatic;
242 | TestTargetID = 23DE14751FBEB52A0010E36B;
243 | };
244 | };
245 | };
246 | buildConfigurationList = 23DE14711FBEB52A0010E36B /* Build configuration list for PBXProject "skoal-example" */;
247 | compatibilityVersion = "Xcode 8.0";
248 | developmentRegion = en;
249 | hasScannedForEncodings = 0;
250 | knownRegions = (
251 | en,
252 | Base,
253 | );
254 | mainGroup = 23DE146D1FBEB52A0010E36B;
255 | productRefGroup = 23DE14771FBEB52A0010E36B /* Products */;
256 | projectDirPath = "";
257 | projectRoot = "";
258 | targets = (
259 | 23DE14751FBEB52A0010E36B /* skoal-example */,
260 | 23DE14891FBEB52B0010E36B /* skoal-exampleTests */,
261 | 23DE14941FBEB52B0010E36B /* skoal-exampleUITests */,
262 | );
263 | };
264 | /* End PBXProject section */
265 |
266 | /* Begin PBXResourcesBuildPhase section */
267 | 23DE14741FBEB52A0010E36B /* Resources */ = {
268 | isa = PBXResourcesBuildPhase;
269 | buildActionMask = 2147483647;
270 | files = (
271 | 23DE14841FBEB52B0010E36B /* LaunchScreen.storyboard in Resources */,
272 | 23DE14811FBEB52B0010E36B /* Assets.xcassets in Resources */,
273 | 23DE147F1FBEB52A0010E36B /* Main.storyboard in Resources */,
274 | );
275 | runOnlyForDeploymentPostprocessing = 0;
276 | };
277 | 23DE14881FBEB52B0010E36B /* Resources */ = {
278 | isa = PBXResourcesBuildPhase;
279 | buildActionMask = 2147483647;
280 | files = (
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | 23DE14931FBEB52B0010E36B /* Resources */ = {
285 | isa = PBXResourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | );
289 | runOnlyForDeploymentPostprocessing = 0;
290 | };
291 | /* End PBXResourcesBuildPhase section */
292 |
293 | /* Begin PBXSourcesBuildPhase section */
294 | 23DE14721FBEB52A0010E36B /* Sources */ = {
295 | isa = PBXSourcesBuildPhase;
296 | buildActionMask = 2147483647;
297 | files = (
298 | 23DE14B71FBEB5F70010E36B /* skoal.m in Sources */,
299 | 23DE14AC1FBEB5580010E36B /* ViewController.swift in Sources */,
300 | 23DE147A1FBEB52A0010E36B /* AppDelegate.swift in Sources */,
301 | );
302 | runOnlyForDeploymentPostprocessing = 0;
303 | };
304 | 23DE14861FBEB52B0010E36B /* Sources */ = {
305 | isa = PBXSourcesBuildPhase;
306 | buildActionMask = 2147483647;
307 | files = (
308 | 23DE148F1FBEB52B0010E36B /* skoal_exampleTests.swift in Sources */,
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | };
312 | 23DE14911FBEB52B0010E36B /* Sources */ = {
313 | isa = PBXSourcesBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | 23DE149A1FBEB52B0010E36B /* skoal_exampleUITests.swift in Sources */,
317 | );
318 | runOnlyForDeploymentPostprocessing = 0;
319 | };
320 | /* End PBXSourcesBuildPhase section */
321 |
322 | /* Begin PBXTargetDependency section */
323 | 23DE148C1FBEB52B0010E36B /* PBXTargetDependency */ = {
324 | isa = PBXTargetDependency;
325 | target = 23DE14751FBEB52A0010E36B /* skoal-example */;
326 | targetProxy = 23DE148B1FBEB52B0010E36B /* PBXContainerItemProxy */;
327 | };
328 | 23DE14971FBEB52B0010E36B /* PBXTargetDependency */ = {
329 | isa = PBXTargetDependency;
330 | target = 23DE14751FBEB52A0010E36B /* skoal-example */;
331 | targetProxy = 23DE14961FBEB52B0010E36B /* PBXContainerItemProxy */;
332 | };
333 | /* End PBXTargetDependency section */
334 |
335 | /* Begin PBXVariantGroup section */
336 | 23DE147D1FBEB52A0010E36B /* Main.storyboard */ = {
337 | isa = PBXVariantGroup;
338 | children = (
339 | 23DE147E1FBEB52A0010E36B /* Base */,
340 | );
341 | name = Main.storyboard;
342 | sourceTree = "";
343 | };
344 | 23DE14821FBEB52B0010E36B /* LaunchScreen.storyboard */ = {
345 | isa = PBXVariantGroup;
346 | children = (
347 | 23DE14831FBEB52B0010E36B /* Base */,
348 | );
349 | name = LaunchScreen.storyboard;
350 | sourceTree = "";
351 | };
352 | /* End PBXVariantGroup section */
353 |
354 | /* Begin XCBuildConfiguration section */
355 | 23DE149C1FBEB52B0010E36B /* Debug */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | ALWAYS_SEARCH_USER_PATHS = NO;
359 | CLANG_ANALYZER_NONNULL = YES;
360 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
362 | CLANG_CXX_LIBRARY = "libc++";
363 | CLANG_ENABLE_MODULES = YES;
364 | CLANG_ENABLE_OBJC_ARC = YES;
365 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
366 | CLANG_WARN_BOOL_CONVERSION = YES;
367 | CLANG_WARN_COMMA = YES;
368 | CLANG_WARN_CONSTANT_CONVERSION = YES;
369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
370 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
371 | CLANG_WARN_EMPTY_BODY = YES;
372 | CLANG_WARN_ENUM_CONVERSION = YES;
373 | CLANG_WARN_INFINITE_RECURSION = YES;
374 | CLANG_WARN_INT_CONVERSION = YES;
375 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
376 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
377 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
378 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
379 | CLANG_WARN_STRICT_PROTOTYPES = YES;
380 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
381 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
382 | CLANG_WARN_UNREACHABLE_CODE = YES;
383 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
384 | CODE_SIGN_IDENTITY = "iPhone Developer";
385 | COPY_PHASE_STRIP = NO;
386 | DEBUG_INFORMATION_FORMAT = dwarf;
387 | ENABLE_STRICT_OBJC_MSGSEND = YES;
388 | ENABLE_TESTABILITY = YES;
389 | GCC_C_LANGUAGE_STANDARD = gnu11;
390 | GCC_DYNAMIC_NO_PIC = NO;
391 | GCC_NO_COMMON_BLOCKS = YES;
392 | GCC_OPTIMIZATION_LEVEL = 0;
393 | GCC_PREPROCESSOR_DEFINITIONS = (
394 | "DEBUG=1",
395 | "$(inherited)",
396 | );
397 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
398 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
399 | GCC_WARN_UNDECLARED_SELECTOR = YES;
400 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
401 | GCC_WARN_UNUSED_FUNCTION = YES;
402 | GCC_WARN_UNUSED_VARIABLE = YES;
403 | IPHONEOS_DEPLOYMENT_TARGET = 11.1;
404 | MTL_ENABLE_DEBUG_INFO = YES;
405 | ONLY_ACTIVE_ARCH = YES;
406 | SDKROOT = iphoneos;
407 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
408 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
409 | };
410 | name = Debug;
411 | };
412 | 23DE149D1FBEB52B0010E36B /* Release */ = {
413 | isa = XCBuildConfiguration;
414 | buildSettings = {
415 | ALWAYS_SEARCH_USER_PATHS = NO;
416 | CLANG_ANALYZER_NONNULL = YES;
417 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
418 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
419 | CLANG_CXX_LIBRARY = "libc++";
420 | CLANG_ENABLE_MODULES = YES;
421 | CLANG_ENABLE_OBJC_ARC = YES;
422 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
423 | CLANG_WARN_BOOL_CONVERSION = YES;
424 | CLANG_WARN_COMMA = YES;
425 | CLANG_WARN_CONSTANT_CONVERSION = YES;
426 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
427 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
428 | CLANG_WARN_EMPTY_BODY = YES;
429 | CLANG_WARN_ENUM_CONVERSION = YES;
430 | CLANG_WARN_INFINITE_RECURSION = YES;
431 | CLANG_WARN_INT_CONVERSION = YES;
432 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
433 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
434 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
435 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
436 | CLANG_WARN_STRICT_PROTOTYPES = YES;
437 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
438 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
439 | CLANG_WARN_UNREACHABLE_CODE = YES;
440 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
441 | CODE_SIGN_IDENTITY = "iPhone Developer";
442 | COPY_PHASE_STRIP = NO;
443 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
444 | ENABLE_NS_ASSERTIONS = NO;
445 | ENABLE_STRICT_OBJC_MSGSEND = YES;
446 | GCC_C_LANGUAGE_STANDARD = gnu11;
447 | GCC_NO_COMMON_BLOCKS = YES;
448 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
449 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
450 | GCC_WARN_UNDECLARED_SELECTOR = YES;
451 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
452 | GCC_WARN_UNUSED_FUNCTION = YES;
453 | GCC_WARN_UNUSED_VARIABLE = YES;
454 | IPHONEOS_DEPLOYMENT_TARGET = 11.1;
455 | MTL_ENABLE_DEBUG_INFO = NO;
456 | SDKROOT = iphoneos;
457 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
458 | VALIDATE_PRODUCT = YES;
459 | };
460 | name = Release;
461 | };
462 | 23DE149F1FBEB52B0010E36B /* Debug */ = {
463 | isa = XCBuildConfiguration;
464 | buildSettings = {
465 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
466 | CLANG_ENABLE_MODULES = YES;
467 | CODE_SIGN_ENTITLEMENTS = "skoal-example/skoal-example.entitlements";
468 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
469 | CODE_SIGN_STYLE = Automatic;
470 | DEVELOPMENT_TEAM = 49BQNS38WU;
471 | INFOPLIST_FILE = "skoal-example/Info.plist";
472 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
474 | PRODUCT_BUNDLE_IDENTIFIER = "com.BANYAN.skoal-example";
475 | PRODUCT_NAME = "$(TARGET_NAME)";
476 | PROVISIONING_PROFILE_SPECIFIER = "";
477 | SWIFT_OBJC_BRIDGING_HEADER = "skoal-example/skoal-example-Bridging-Header.h";
478 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
479 | SWIFT_VERSION = 4.0;
480 | TARGETED_DEVICE_FAMILY = "1,2";
481 | };
482 | name = Debug;
483 | };
484 | 23DE14A01FBEB52B0010E36B /* Release */ = {
485 | isa = XCBuildConfiguration;
486 | buildSettings = {
487 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
488 | CLANG_ENABLE_MODULES = YES;
489 | CODE_SIGN_ENTITLEMENTS = "skoal-example/skoal-example.entitlements";
490 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
491 | CODE_SIGN_STYLE = Automatic;
492 | DEVELOPMENT_TEAM = 49BQNS38WU;
493 | INFOPLIST_FILE = "skoal-example/Info.plist";
494 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
496 | PRODUCT_BUNDLE_IDENTIFIER = "com.BANYAN.skoal-example";
497 | PRODUCT_NAME = "$(TARGET_NAME)";
498 | PROVISIONING_PROFILE_SPECIFIER = "";
499 | SWIFT_OBJC_BRIDGING_HEADER = "skoal-example/skoal-example-Bridging-Header.h";
500 | SWIFT_VERSION = 4.0;
501 | TARGETED_DEVICE_FAMILY = "1,2";
502 | };
503 | name = Release;
504 | };
505 | 23DE14A21FBEB52B0010E36B /* Debug */ = {
506 | isa = XCBuildConfiguration;
507 | buildSettings = {
508 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
509 | BUNDLE_LOADER = "$(TEST_HOST)";
510 | CODE_SIGN_STYLE = Automatic;
511 | INFOPLIST_FILE = "skoal-exampleTests/Info.plist";
512 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
513 | PRODUCT_BUNDLE_IDENTIFIER = "BANYAN.skoal-exampleTests";
514 | PRODUCT_NAME = "$(TARGET_NAME)";
515 | SWIFT_VERSION = 4.0;
516 | TARGETED_DEVICE_FAMILY = "1,2";
517 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/skoal-example.app/skoal-example";
518 | };
519 | name = Debug;
520 | };
521 | 23DE14A31FBEB52B0010E36B /* Release */ = {
522 | isa = XCBuildConfiguration;
523 | buildSettings = {
524 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
525 | BUNDLE_LOADER = "$(TEST_HOST)";
526 | CODE_SIGN_STYLE = Automatic;
527 | INFOPLIST_FILE = "skoal-exampleTests/Info.plist";
528 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
529 | PRODUCT_BUNDLE_IDENTIFIER = "BANYAN.skoal-exampleTests";
530 | PRODUCT_NAME = "$(TARGET_NAME)";
531 | SWIFT_VERSION = 4.0;
532 | TARGETED_DEVICE_FAMILY = "1,2";
533 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/skoal-example.app/skoal-example";
534 | };
535 | name = Release;
536 | };
537 | 23DE14A51FBEB52B0010E36B /* Debug */ = {
538 | isa = XCBuildConfiguration;
539 | buildSettings = {
540 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
541 | CODE_SIGN_STYLE = Automatic;
542 | INFOPLIST_FILE = "skoal-exampleUITests/Info.plist";
543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
544 | PRODUCT_BUNDLE_IDENTIFIER = "BANYAN.skoal-exampleUITests";
545 | PRODUCT_NAME = "$(TARGET_NAME)";
546 | SWIFT_VERSION = 4.0;
547 | TARGETED_DEVICE_FAMILY = "1,2";
548 | TEST_TARGET_NAME = "skoal-example";
549 | };
550 | name = Debug;
551 | };
552 | 23DE14A61FBEB52B0010E36B /* Release */ = {
553 | isa = XCBuildConfiguration;
554 | buildSettings = {
555 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
556 | CODE_SIGN_STYLE = Automatic;
557 | INFOPLIST_FILE = "skoal-exampleUITests/Info.plist";
558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
559 | PRODUCT_BUNDLE_IDENTIFIER = "BANYAN.skoal-exampleUITests";
560 | PRODUCT_NAME = "$(TARGET_NAME)";
561 | SWIFT_VERSION = 4.0;
562 | TARGETED_DEVICE_FAMILY = "1,2";
563 | TEST_TARGET_NAME = "skoal-example";
564 | };
565 | name = Release;
566 | };
567 | /* End XCBuildConfiguration section */
568 |
569 | /* Begin XCConfigurationList section */
570 | 23DE14711FBEB52A0010E36B /* Build configuration list for PBXProject "skoal-example" */ = {
571 | isa = XCConfigurationList;
572 | buildConfigurations = (
573 | 23DE149C1FBEB52B0010E36B /* Debug */,
574 | 23DE149D1FBEB52B0010E36B /* Release */,
575 | );
576 | defaultConfigurationIsVisible = 0;
577 | defaultConfigurationName = Release;
578 | };
579 | 23DE149E1FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-example" */ = {
580 | isa = XCConfigurationList;
581 | buildConfigurations = (
582 | 23DE149F1FBEB52B0010E36B /* Debug */,
583 | 23DE14A01FBEB52B0010E36B /* Release */,
584 | );
585 | defaultConfigurationIsVisible = 0;
586 | defaultConfigurationName = Release;
587 | };
588 | 23DE14A11FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-exampleTests" */ = {
589 | isa = XCConfigurationList;
590 | buildConfigurations = (
591 | 23DE14A21FBEB52B0010E36B /* Debug */,
592 | 23DE14A31FBEB52B0010E36B /* Release */,
593 | );
594 | defaultConfigurationIsVisible = 0;
595 | defaultConfigurationName = Release;
596 | };
597 | 23DE14A41FBEB52B0010E36B /* Build configuration list for PBXNativeTarget "skoal-exampleUITests" */ = {
598 | isa = XCConfigurationList;
599 | buildConfigurations = (
600 | 23DE14A51FBEB52B0010E36B /* Debug */,
601 | 23DE14A61FBEB52B0010E36B /* Release */,
602 | );
603 | defaultConfigurationIsVisible = 0;
604 | defaultConfigurationName = Release;
605 | };
606 | /* End XCConfigurationList section */
607 | };
608 | rootObject = 23DE146E1FBEB52A0010E36B /* Project object */;
609 | }
610 |
--------------------------------------------------------------------------------
/skoal/skoal.m:
--------------------------------------------------------------------------------
1 | // skoal.m
2 | //
3 | // Copyright (c) 2017 BANYAN
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in
13 | // all copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | // THE SOFTWARE.
22 |
23 | #import "skoal.h"
24 |
25 | static skoal *_instance = nil;
26 |
27 | @implementation skoal
28 |
29 | +(instancetype)sharedInstance{
30 | static dispatch_once_t onceToken;
31 | dispatch_once(&onceToken, ^{
32 | _instance = [[self alloc] init];
33 | });
34 | return _instance;
35 | }
36 | +(instancetype)allocWithZone:(struct _NSZone *)zone{
37 | static dispatch_once_t onceToken;
38 | dispatch_once(&onceToken, ^{
39 | _instance = [super allocWithZone:zone];
40 | });
41 | return _instance;
42 | }
43 | +(instancetype)copyWithZone:(nullable NSZone *)zone{
44 | return _instance;
45 | }
46 |
47 | -(instancetype)init{
48 | if (self = [super init]) {
49 | self.store = [[HKHealthStore alloc] init];
50 | }
51 | return self;
52 | }
53 |
54 |
55 | ///-------------------------
56 | #pragma mark - 获取权限
57 | ///-------------------------
58 | -(void)requestHealthPermissionWithBlock:(HealthStorePermissionResponseBlock)block
59 | {
60 | if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 8.0) {
61 | if (![HKHealthStore isHealthDataAvailable]) {
62 | DLog(@"skoal:该设备不支持HealthKit");
63 | }else{
64 | HKHealthStore *store = [[HKHealthStore alloc] init];
65 | NSSet *readObjectTypes = [self readObjectTypes];
66 | NSSet *writeObjectTypes = [self writeObjectTypes];
67 | [store requestAuthorizationToShareTypes:writeObjectTypes readTypes:readObjectTypes completion:^(BOOL success, NSError * _Nullable error) {
68 | if (success == YES) {
69 | block(HealthStorePermissionResponseSuccess);
70 | }else{
71 | block(HealthStorePermissionResponseError);
72 | }
73 | }];
74 | }
75 | }else{
76 | DLog(@"skoal:HealthKit暂不支持iOS8以下系统,请更新你的系统。");
77 | }
78 | }
79 |
80 |
81 | ///-------------------------
82 | #pragma mark - 步数
83 | ///-------------------------
84 | -(void)readStepCountFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion;
85 | {
86 | HKSampleType *stepCountType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
87 |
88 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
89 |
90 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
91 |
92 | NSPredicate *predicate = [self predicateSampleByToday];
93 |
94 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:stepCountType predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
95 |
96 | double sum = 0;
97 | for (HKQuantitySample *sample in results) {
98 | sum += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
99 | }
100 |
101 | completion(sum,error);
102 | }];
103 |
104 | [self.store executeQuery:query];
105 | }
106 | -(void)readStepCountFromHealthStoreWithStartTime:(NSString *)startTime endTime:(NSString *)endTime completion:(void(^)(double value,NSError *error))completion
107 | {
108 | HKSampleType *stepCountType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
109 |
110 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
111 |
112 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
113 |
114 | NSPredicate *predicate = [self predicateSampleByPeriodOfTimeWithStartTime:startTime endTime:endTime];
115 |
116 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:stepCountType predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
117 |
118 | double sum = 0;
119 | for (HKQuantitySample *sample in results) {
120 | sum += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
121 | }
122 |
123 | completion(sum,error);
124 | }];
125 |
126 | [self.store executeQuery:query];
127 | }
128 | -(void)writeStepCountToHealthStoreWithUnit:(double)setpCount completion:(void(^)(BOOL response))completion
129 | {
130 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
131 |
132 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:setpCount];
133 |
134 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
135 |
136 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
137 | if (success) {
138 | completion(YES);
139 | }else {
140 | completion(NO);
141 | }
142 | }];
143 | }
144 | -(void)writeStepCountToHealthStoreWithUnit:(double)setpCount startTime:(NSString *)startTime endTime:(NSString *)endTime completion:(void(^)(BOOL response))completion
145 | {
146 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
147 |
148 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:setpCount];
149 |
150 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
151 | [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
152 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
153 |
154 | NSDate *newStartDate = [formatter dateFromString:startTime];
155 | NSDate *newEndDate = [formatter dateFromString:endTime];
156 |
157 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:newStartDate endDate:newEndDate metadata:nil];
158 |
159 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
160 | if (success) {
161 | completion(YES);
162 | }else {
163 | completion(NO);
164 | }
165 | }];
166 | }
167 |
168 |
169 | ///-------------------------
170 | #pragma mark - 身高
171 | ///-------------------------
172 | -(void)readHeightFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
173 | {
174 | HKSampleType *heightType = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
175 |
176 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
177 |
178 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
179 |
180 | NSPredicate *predicate = [self predicateSampleByLatestData];
181 |
182 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:heightType predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
183 |
184 | double height = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
185 |
186 | completion(height,error);
187 | }];
188 |
189 | [self.store executeQuery:query];
190 | }
191 | -(void)writeHeightToHealthStoreWithUnit:(double)Height completion:(void(^)(BOOL response))completion
192 | {
193 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
194 |
195 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit meterUnit] doubleValue:Height];
196 |
197 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
198 |
199 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
200 | if (success) {
201 | completion(YES);
202 | }else {
203 | completion(NO);
204 | }
205 | }];
206 | }
207 |
208 |
209 | ///-------------------------
210 | #pragma mark - 体重
211 | ///-------------------------
212 | -(void)readBodyMassFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
213 | {
214 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
215 |
216 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
217 |
218 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
219 |
220 | NSPredicate *predicate = [self predicateSampleByLatestData];
221 |
222 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
223 |
224 | double bodyMass = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
225 |
226 | completion(bodyMass,error);
227 | }];
228 |
229 | [self.store executeQuery:query];
230 | }
231 | -(void)writeBodyMassToHealthStoreWithUnit:(double)bodyMass completion:(void(^)(BOOL response))completion
232 | {
233 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
234 |
235 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit gramUnit] doubleValue:bodyMass * 1000];
236 |
237 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
238 |
239 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
240 | if (success) {
241 | completion(YES);
242 | }else {
243 | completion(NO);
244 | }
245 | }];
246 | }
247 |
248 |
249 | ///-------------------------
250 | #pragma mark - 身体质量指数
251 | ///-------------------------
252 | -(void)readBodyMassIndexFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
253 | {
254 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
255 |
256 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
257 |
258 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
259 |
260 | NSPredicate *predicate = [self predicateSampleByLatestData];
261 |
262 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
263 |
264 | double bodyMassIndex = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
265 |
266 | completion(bodyMassIndex,error);
267 | }];
268 |
269 | [self.store executeQuery:query];
270 | }
271 | -(void)writeBodyMassIndexToHealthStoreWithUnit:(double)bodyMassIndex completion:(void(^)(BOOL response))completion
272 | {
273 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
274 |
275 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:bodyMassIndex];
276 |
277 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
278 |
279 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
280 | if (success) {
281 | completion(YES);
282 | }else {
283 | completion(NO);
284 | }
285 | }];
286 | }
287 |
288 |
289 | ///-------------------------
290 | #pragma mark - 步行&跑步距离
291 | ///-------------------------
292 | -(void)readDistanceWalkingRunningFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
293 | {
294 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
295 |
296 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
297 |
298 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
299 |
300 | NSPredicate *predicate = [self predicateSampleByToday];
301 |
302 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
303 |
304 | double distanceWalkingRunning = 0;
305 | for (HKQuantitySample *sample in results) {
306 | distanceWalkingRunning += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
307 | }
308 |
309 | completion(distanceWalkingRunning / 1000,error);
310 | }];
311 |
312 | [self.store executeQuery:query];
313 | }
314 | -(void)writeDistanceWalkingRunningToHealthStoreWithUnit:(double)distanceWalkingRunning completion:(void(^)(BOOL response))completion
315 | {
316 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
317 |
318 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit meterUnit] doubleValue:distanceWalkingRunning * 1000];
319 |
320 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
321 |
322 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
323 | if (success) {
324 | completion(YES);
325 | }else {
326 | completion(NO);
327 | }
328 | }];
329 | }
330 |
331 |
332 | ///-------------------------
333 | #pragma mark - 以爬楼层
334 | ///-------------------------
335 | -(void)readFlightsClimbedFromHealthStoreWithCompletion:(void(^)(NSInteger value,NSError *error))completion
336 | {
337 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed];
338 |
339 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
340 |
341 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
342 |
343 | NSPredicate *predicate = [self predicateSampleByToday];
344 |
345 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
346 |
347 | double flightsClimbed = 0;
348 | for (HKQuantitySample *sample in results) {
349 | flightsClimbed += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
350 | }
351 |
352 | completion(flightsClimbed,error);
353 | }];
354 |
355 | [self.store executeQuery:query];
356 | }
357 | -(void)writeFlightsClimbedToHealthStoreWithUnit:(NSInteger)flightsClimbed completion:(void(^)(BOOL response))completion;
358 | {
359 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed];
360 |
361 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:flightsClimbed];
362 |
363 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
364 |
365 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
366 | if (success) {
367 | completion(YES);
368 | }else {
369 | completion(NO);
370 | }
371 | }];
372 | }
373 |
374 |
375 | ///-------------------------
376 | #pragma mark - 呼吸速率
377 | ///-------------------------
378 | -(void)readRespiratoryRateFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
379 | {
380 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate];
381 |
382 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
383 |
384 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
385 |
386 | NSPredicate *predicate = [self predicateSampleByLatestData];
387 |
388 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
389 |
390 | double respiratoryRate = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
391 |
392 | completion(respiratoryRate,error);
393 | }];
394 |
395 | [self.store executeQuery:query];
396 | }
397 | -(void)writeRespiratoryRateToHealthStoreWithUnit:(double)respiratoryRate completion:(void(^)(BOOL response))completion
398 | {
399 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate];
400 |
401 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit unitFromString:@"count/min"] doubleValue:respiratoryRate];
402 |
403 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
404 |
405 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
406 | if (success) {
407 | completion(YES);
408 | }else {
409 | completion(NO);
410 | }
411 | }];
412 | }
413 |
414 |
415 | ///-------------------------
416 | #pragma mark - DietaryEnergyConsumed(膳食能量消耗)
417 | ///-------------------------
418 | -(void)readDietaryEnergyConsumedFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
419 | {
420 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryEnergyConsumed];
421 |
422 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
423 |
424 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
425 |
426 | NSPredicate *predicate = [self predicateSampleByLatestData];
427 |
428 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
429 |
430 | double dietaryEnergyConsumed = 0;
431 | for (HKQuantitySample *sample in results) {
432 | dietaryEnergyConsumed += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
433 | }
434 |
435 | completion(dietaryEnergyConsumed,error);
436 | }];
437 |
438 | [self.store executeQuery:query];
439 | }
440 | -(void)writeDietaryEnergyConsumedToHealthStoreWithUnit:(double)dietaryEnergyConsumed completion:(void(^)(BOOL response))completion
441 | {
442 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryEnergyConsumed];
443 |
444 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit kilocalorieUnit] doubleValue:dietaryEnergyConsumed];
445 |
446 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
447 |
448 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
449 | if (success) {
450 | completion(YES);
451 | }else {
452 | completion(NO);
453 | }
454 | }];
455 | }
456 |
457 |
458 | ///-------------------------
459 | #pragma mark - OxygenSaturation(血氧饱和度)
460 | ///-------------------------
461 | -(void)readOxygenSaturationFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
462 | {
463 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation];
464 |
465 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
466 |
467 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
468 |
469 | NSPredicate *predicate = [self predicateSampleByLatestData];
470 |
471 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
472 |
473 | double oxygenSaturation = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
474 |
475 | completion(oxygenSaturation,error);
476 | }];
477 |
478 | [self.store executeQuery:query];
479 | }
480 |
481 |
482 | ///-------------------------
483 | #pragma mark - BodyTemperature(体温)
484 | ///-------------------------
485 | -(void)readBodyTemperatureFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
486 | {
487 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
488 |
489 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
490 |
491 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
492 |
493 | NSPredicate *predicate = [self predicateSampleByLatestData];
494 |
495 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
496 |
497 | double bodyTemperature = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
498 |
499 | completion(bodyTemperature,error);
500 | }];
501 |
502 | [self.store executeQuery:query];
503 | }
504 | -(void)writeBodyTemperatureToHealthStoreWithUnit:(double)bodyTemperature completion:(void(^)(BOOL response))completion
505 | {
506 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
507 |
508 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit degreeCelsiusUnit] doubleValue:bodyTemperature];
509 |
510 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
511 |
512 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
513 | if (success) {
514 | completion(YES);
515 | }else {
516 | completion(NO);
517 | }
518 | }];
519 | }
520 |
521 |
522 | ///-------------------------
523 | #pragma mark - BloodGlucose(血糖)
524 | ///-------------------------
525 | -(void)readBloodGlucoseFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
526 | {
527 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose];
528 |
529 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
530 |
531 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
532 |
533 | NSPredicate *predicate = [self predicateSampleByLatestData];
534 |
535 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
536 |
537 | double bloodGlucose = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
538 |
539 | completion(bloodGlucose,error);
540 | }];
541 |
542 | [self.store executeQuery:query];
543 | }
544 | -(void)writeBloodGlucoseToHealthStoreWithUnit:(double)bloodGlucose completion:(void(^)(BOOL response))completion
545 | {
546 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose];
547 |
548 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit unitFromString:@"mg/dl"] doubleValue:bloodGlucose];
549 |
550 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
551 |
552 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
553 | if (success) {
554 | completion(YES);
555 | }else {
556 | completion(NO);
557 | }
558 | }];
559 | }
560 |
561 |
562 | ///-------------------------
563 | #pragma mark - BloodPressure(血压)
564 | ///-------------------------
565 | -(void)readBloodPressureSystolicFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
566 | {
567 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic];
568 |
569 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
570 |
571 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
572 |
573 | NSPredicate *predicate = [self predicateSampleByLatestData];
574 |
575 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
576 |
577 | double bloodPressureSystolic = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
578 |
579 | completion(bloodPressureSystolic,error);
580 | }];
581 |
582 | [self.store executeQuery:query];
583 | }
584 | -(void)writeBloodPressureSystolicToHealthStoreWithUnit:(double)bloodPressureSystolic completion:(void(^)(BOOL response))completion
585 | {
586 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic];
587 |
588 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit millimeterOfMercuryUnit] doubleValue:bloodPressureSystolic];
589 |
590 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
591 |
592 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
593 | if (success) {
594 | completion(YES);
595 | }else {
596 | completion(NO);
597 | }
598 | }];
599 | }
600 | -(void)readBloodPressureDiastolicFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
601 | {
602 | HKSampleType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic];
603 |
604 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
605 |
606 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
607 |
608 | NSPredicate *predicate = [self predicateSampleByLatestData];
609 |
610 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
611 |
612 | double bloodPressureDiastolic = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
613 |
614 | completion(bloodPressureDiastolic,error);
615 | }];
616 |
617 | [self.store executeQuery:query];
618 | }
619 | -(void)writeBloodPressureDiastolicToHealthStoreWithUnit:(double)bloodPressureDiastolic completion:(void(^)(BOOL response))completion
620 | {
621 | HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic];
622 |
623 | HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit millimeterOfMercuryUnit] doubleValue:bloodPressureDiastolic];
624 |
625 | HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:[NSDate date] endDate:[NSDate date] metadata:nil];
626 |
627 | [self.store saveObject:sample withCompletion:^(BOOL success, NSError *error) {
628 | if (success) {
629 | completion(YES);
630 | }else {
631 | completion(NO);
632 | }
633 | }];
634 | }
635 |
636 |
637 | ///-------------------------
638 | #pragma mark - StandHour(站立小时)
639 | ///-------------------------
640 | -(void)readStandHourFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
641 | {
642 | HKSampleType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierAppleStandHour];
643 |
644 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
645 |
646 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
647 |
648 | NSPredicate *predicate = [self predicateSampleByToday];
649 |
650 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
651 |
652 | double sum = 0;
653 | for (HKQuantitySample *sample in results) {
654 | sum += [[[NSString stringWithFormat:@"%@",sample.quantity] componentsSeparatedByString:@" "][0] doubleValue];
655 | }
656 |
657 | completion(sum,error);
658 | }];
659 |
660 | [self.store executeQuery:query];
661 | }
662 |
663 |
664 | ///-------------------------
665 | #pragma mark - BiologicalSex(性别)
666 | ///-------------------------
667 | -(void)readBiologicalSexFromHealthStoreWithCompletion:(void(^)(NSString *sex,NSError *error))completion
668 | {
669 | NSError *error = nil;
670 | HKBiologicalSexObject *sexObject = [self.store biologicalSexWithError:&error];
671 |
672 | NSString *sex = nil;
673 | switch (sexObject.biologicalSex) {
674 | case HKBiologicalSexNotSet:
675 | sex = @"未设置";
676 | break;
677 | case HKBiologicalSexMale:
678 | sex = @"女性";
679 | break;
680 | case HKBiologicalSexFemale:
681 | sex = @"男性";
682 | break;
683 | case HKBiologicalSexOther:
684 | sex = @"其它";
685 | break;
686 | default:
687 | break;
688 | }
689 | completion(sex,error);
690 | }
691 |
692 |
693 | ///-------------------------
694 | #pragma mark - DateOfBirth(出生日期)
695 | ///-------------------------
696 | -(void)readDateOfBirthFromHealthStoreWithCompletion:(void(^)(NSDate *date,NSError *error))completion
697 | {
698 | NSError *error = nil;
699 | NSDateComponents *components = [self.store dateOfBirthComponentsWithError:&error];
700 |
701 | NSCalendar *calendar = [NSCalendar currentCalendar];
702 |
703 | NSDate *date = [calendar dateFromComponents:components];
704 |
705 | NSTimeZone *zone = [NSTimeZone systemTimeZone];
706 |
707 | NSTimeInterval interval = [zone secondsFromGMTForDate:date];
708 |
709 | NSDate *dateOfBrith = [date dateByAddingTimeInterval:interval];
710 |
711 | completion(dateOfBrith,error);
712 | }
713 |
714 |
715 | ///-------------------------
716 | #pragma mark - BloodType(血型)
717 | ///-------------------------
718 | -(void)readBloodTypeFromHealthStoreWithCompletion:(void(^)(NSString *bloodType,NSError *error))completion
719 | {
720 | NSError *error = nil;
721 | HKBloodTypeObject *bloodTypeObject = [self.store bloodTypeWithError:&error];
722 |
723 | NSString *type = nil;
724 | switch (bloodTypeObject.bloodType) {
725 | case HKBloodTypeNotSet:
726 | type = @"未设置";
727 | break;
728 | case HKBloodTypeAPositive:
729 | type = @"A型血阳性";
730 | break;
731 | case HKBloodTypeANegative:
732 | type = @"A型血阴性";
733 | break;
734 | case HKBloodTypeBPositive:
735 | type = @"B型血阳性";
736 | break;
737 | case HKBloodTypeBNegative:
738 | type = @"B型血阴性";
739 | break;
740 | case HKBloodTypeABPositive:
741 | type = @"AB型血阳性";
742 | break;
743 | case HKBloodTypeABNegative:
744 | type = @"AB型血阴性";
745 | break;
746 | case HKBloodTypeOPositive:
747 | type = @"O型血阳性";
748 | break;
749 | case HKBloodTypeONegative:
750 | type = @"O型血阴性";
751 | break;
752 | default:
753 | break;
754 | }
755 | completion(type,error);
756 | }
757 |
758 |
759 | ///-------------------------
760 | #pragma mark - FitzpatrickSkin(日光反应型皮肤类型)
761 | ///-------------------------
762 | -(void)readFitzpatrickSkinFromHealthStoreWithCompletion:(void(^)(NSString *skinType,NSError *error))completion
763 | {
764 | NSError *error = nil;
765 | HKFitzpatrickSkinTypeObject *skinTypeObject = [self.store fitzpatrickSkinTypeWithError:&error];
766 |
767 | NSString *type = nil;
768 | switch (skinTypeObject.skinType) {
769 | case HKFitzpatrickSkinTypeNotSet:
770 | type = @"未设置";
771 | break;
772 | case HKFitzpatrickSkinTypeI:
773 | type = @"I型";
774 | break;
775 | case HKFitzpatrickSkinTypeII:
776 | type = @"II型";
777 | break;
778 | case HKFitzpatrickSkinTypeIII:
779 | type = @"III型";
780 | break;
781 | case HKFitzpatrickSkinTypeIV:
782 | type = @"IV型";
783 | break;
784 | case HKFitzpatrickSkinTypeV:
785 | type = @"V型";
786 | break;
787 | case HKFitzpatrickSkinTypeVI:
788 | type = @"VI型";
789 | break;
790 | default:
791 | break;
792 | }
793 | completion(type,error);
794 | }
795 |
796 |
797 | ///-------------------------
798 | #pragma mark - SleepAnalysis(睡眠分析)
799 | ///-------------------------
800 | -(void)readSleepAnalysisFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
801 | {
802 | HKSampleType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];
803 |
804 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
805 |
806 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
807 |
808 | NSPredicate *predicate = [self predicateSampleByToday];
809 |
810 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
811 |
812 | double sleepAnalysis = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
813 |
814 | completion(sleepAnalysis,error);
815 | }];
816 |
817 | [self.store executeQuery:query];
818 | }
819 |
820 |
821 | ///-------------------------
822 | #pragma mark - MenstrualFlow(月经)
823 | ///-------------------------
824 | -(void)readMenstrualFlowFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
825 | {
826 | HKSampleType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMenstrualFlow];
827 |
828 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
829 |
830 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
831 |
832 | NSPredicate *predicate = [self predicateSampleByToday];
833 |
834 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
835 |
836 | double menstrualFlow = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
837 |
838 | completion(menstrualFlow,error);
839 | }];
840 |
841 | [self.store executeQuery:query];
842 | }
843 |
844 |
845 | ///-------------------------
846 | #pragma mark - IntermenstrualBleeding(点滴出血)
847 | ///-------------------------
848 | -(void)readIntermenstrualBleedingFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
849 | {
850 | HKSampleType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierIntermenstrualBleeding];
851 |
852 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
853 |
854 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
855 |
856 | NSPredicate *predicate = [self predicateSampleByToday];
857 |
858 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
859 |
860 | double intermenstrualBleeding = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
861 |
862 | completion(intermenstrualBleeding,error);
863 | }];
864 |
865 | [self.store executeQuery:query];
866 | }
867 |
868 |
869 | ///-------------------------
870 | #pragma mark - SexualActivity(性行为)
871 | ///-------------------------
872 | -(void)readSexualActivityFromHealthStoreWithCompletion:(void(^)(double value,NSError *error))completion
873 | {
874 | HKSampleType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSexualActivity];
875 |
876 | NSSortDescriptor *startSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
877 |
878 | NSSortDescriptor *endSort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
879 |
880 | NSPredicate *predicate = [self predicateSampleByToday];
881 |
882 | HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:0 sortDescriptors:@[startSort,endSort] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
883 |
884 | double sexualActivity = [[[NSString stringWithFormat:@"%@",results.firstObject] componentsSeparatedByString:@" "][0] doubleValue];
885 |
886 | completion(sexualActivity,error);
887 | }];
888 |
889 | [self.store executeQuery:query];
890 | }
891 |
892 |
893 | ///-------------------------
894 | #pragma mark - 谓词样本
895 | ///-------------------------
896 | -(NSPredicate *)predicateSampleByToday //predicate sample is the day data(谓词样本为当天数据)
897 | {
898 | NSCalendar *calendar = [NSCalendar currentCalendar];
899 |
900 | NSDate *dateNow = [NSDate date];
901 |
902 | NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:dateNow];
903 | [components setHour:0];
904 | [components setMinute:0];
905 | [components setSecond:0];
906 |
907 | NSDate *startDate = [calendar dateFromComponents:components];
908 | NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
909 |
910 | NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:(HKQueryOptionNone)];
911 |
912 | return predicate;
913 | }
914 | -(NSPredicate *)predicateSampleByLatestData //predicate sample is the latest data(谓词样本为最新数据)
915 | {
916 | NSCalendar *calendar = [NSCalendar currentCalendar];
917 |
918 | NSDate *dateNow = [NSDate date];
919 |
920 | NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:dateNow];
921 | [components setHour:0];
922 | [components setMinute:0];
923 | [components setSecond:0];
924 |
925 | NSDate *startDate = [calendar dateFromComponents:components];
926 | NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
927 |
928 | NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:0 endDate:endDate options:(HKQueryOptionNone)];
929 |
930 | return predicate;
931 | }
932 | -(NSPredicate *)predicateSampleByPeriodOfTimeWithStartTime:(NSString *)startTime endTime:(NSString *)endTime //predicate sample is time period data(谓词样本为时间段数据)
933 | {
934 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
935 | [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
936 | formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
937 |
938 | NSDate *newStartDate = [formatter dateFromString:startTime];
939 | NSDate *newEndDate = [formatter dateFromString:endTime];
940 |
941 | NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:newStartDate endDate:newEndDate options:(HKQueryOptionNone)];
942 |
943 | return predicate;
944 | }
945 |
946 |
947 | ///-------------------------
948 | #pragma mark - 权限集合
949 | ///-------------------------
950 | -(NSSet *)readObjectTypes ///读权限集合
951 | {
952 | HKQuantityType *Height = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; //身高
953 |
954 | HKQuantityType *BodyMass = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; //体重
955 |
956 | HKQuantityType *BodyMassIndex= [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex]; //身体质量指数
957 |
958 | HKQuantityType *StepCount = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; //步数
959 |
960 | HKQuantityType *DistanceWalkingRunning= [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; //步行 + 跑步距离
961 |
962 | HKObjectType *FlightsClimbed = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; //已爬楼层
963 |
964 | HKQuantityType *RespiratoryRate = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate]; //呼吸速率
965 |
966 | HKQuantityType *DietaryEnergyConsumed = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryEnergyConsumed]; //膳食能量消耗
967 |
968 | HKQuantityType *OxygenSaturation = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation]; //血氧饱和度
969 |
970 | HKQuantityType *BodyTemperature = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature]; //体温
971 |
972 | HKQuantityType *BloodGlucose = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose]; //血糖
973 |
974 | HKQuantityType *BloodPressureSystolic = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]; //血压收缩压
975 |
976 | HKQuantityType *BloodPressureDiastolic = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic]; //血压舒张压
977 |
978 | HKCategoryType *StandHour = [HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierAppleStandHour]; //站立小时
979 |
980 | HKObjectType *ActivitySummary = [HKObjectType activitySummaryType]; //健身记录
981 |
982 | HKObjectType *BiologicalSex = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]; //性别
983 |
984 | HKObjectType *DateOfBirth = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth]; //出生日期
985 |
986 | HKObjectType *BloodType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]; //血型
987 |
988 | HKObjectType *FitzpatrickSkin = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType]; //日光反应型皮肤类型
989 |
990 | HKObjectType *SleepAnalysis = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis]; //睡眠分析
991 |
992 | HKObjectType *MenstrualFlow = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMenstrualFlow]; //月经
993 |
994 | HKObjectType *IntermenstrualBleeding = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierIntermenstrualBleeding]; //点滴出血
995 |
996 | HKObjectType *SexualActivity = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSexualActivity]; //性行为
997 |
998 | return [NSSet setWithObjects:Height,
999 | BodyMass,
1000 | BodyMassIndex,
1001 | StepCount,
1002 | DistanceWalkingRunning,
1003 | FlightsClimbed,
1004 | RespiratoryRate,
1005 | DietaryEnergyConsumed,
1006 | OxygenSaturation,
1007 | BodyTemperature,
1008 | BloodGlucose,
1009 | BloodPressureSystolic,
1010 | BloodPressureDiastolic,
1011 | StandHour,
1012 | ActivitySummary,
1013 | BiologicalSex,
1014 | DateOfBirth,
1015 | BloodType,
1016 | FitzpatrickSkin,
1017 | SleepAnalysis,
1018 | MenstrualFlow,
1019 | IntermenstrualBleeding,
1020 | SexualActivity,
1021 | nil];
1022 | }
1023 | -(NSSet *)writeObjectTypes ///写权限集合
1024 | {
1025 | HKQuantityType *Height = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; //身高
1026 |
1027 | HKQuantityType *BodyMass = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; //体重
1028 |
1029 | HKQuantityType *BodyMassIndex= [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex]; //身体质量指数
1030 |
1031 | HKQuantityType *StepCount = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; //步数
1032 |
1033 | HKQuantityType *DistanceWalkingRunning= [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; //步行 + 跑步距离
1034 |
1035 | HKObjectType *FlightsClimbed = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; //已爬楼层
1036 |
1037 | HKQuantityType *RespiratoryRate = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate]; //呼吸速率
1038 |
1039 | HKQuantityType *DietaryEnergyConsumed = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryEnergyConsumed]; //膳食能量消耗
1040 |
1041 | HKQuantityType *OxygenSaturation = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation]; //血氧饱和度
1042 |
1043 | HKQuantityType *BodyTemperature = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature]; //体温
1044 |
1045 | HKQuantityType *BloodGlucose = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose]; //血糖
1046 |
1047 | HKQuantityType *BloodPressureSystolic = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]; //血压收缩压
1048 |
1049 | HKQuantityType *BloodPressureDiastolic = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic]; //血压舒张压
1050 |
1051 | HKObjectType *SleepAnalysis = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis]; //睡眠分析
1052 |
1053 | HKObjectType *MenstrualFlow = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMenstrualFlow]; //月经
1054 |
1055 | HKObjectType *IntermenstrualBleeding = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierIntermenstrualBleeding]; //点滴出血
1056 |
1057 | HKObjectType *SexualActivity = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSexualActivity]; //性行为
1058 |
1059 | return [NSSet setWithObjects:Height,
1060 | BodyMass,
1061 | BodyMassIndex,
1062 | StepCount,
1063 | DistanceWalkingRunning,
1064 | FlightsClimbed,
1065 | RespiratoryRate,
1066 | DietaryEnergyConsumed,
1067 | OxygenSaturation,
1068 | BodyTemperature,
1069 | BloodGlucose,
1070 | BloodPressureSystolic,
1071 | BloodPressureDiastolic,
1072 | SleepAnalysis,
1073 | MenstrualFlow,
1074 | IntermenstrualBleeding,
1075 | SexualActivity,
1076 | nil];
1077 | }
1078 |
1079 | @end
1080 |
--------------------------------------------------------------------------------