├── Design ├── Logo.png └── heart-control.sketch ├── Heart Control ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Contents.json │ └── Heart Control.imageset │ │ ├── Heart Control.png │ │ └── Contents.json ├── Heart Control.entitlements ├── ViewController.swift ├── AppDelegate.swift ├── Info.plist └── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Heart Control WatchKit App ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Icon-24@2x.png │ │ ├── Icon-29@2x.png │ │ ├── Icon-29@3x.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-44@2x.png │ │ ├── Icon-86@2x.png │ │ ├── Icon-98@2x.png │ │ ├── Icon-27.5@2x.png │ │ └── Contents.json ├── Info.plist └── Base.lproj │ └── Interface.storyboard ├── Heart Control.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── Heart Control WatchKit Extension ├── Heart Control WatchKit Extension.entitlements ├── HeartRate.swift ├── HKUnit+BeatsPerMinute.swift ├── Assets.xcassets │ └── Complication.complicationset │ │ ├── Circular.imageset │ │ └── Contents.json │ │ ├── Modular.imageset │ │ └── Contents.json │ │ ├── Utilitarian.imageset │ │ └── Contents.json │ │ └── Contents.json ├── AuthorizationManger.swift ├── Info.plist ├── ExtensionDelegate.swift ├── InterfaceController.swift ├── HeartRateManager.swift └── WorkoutManager.swift ├── .gitignore └── README.md /Design/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Design/Logo.png -------------------------------------------------------------------------------- /Design/heart-control.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Design/heart-control.sketch -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/Heart Control.imageset/Heart Control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/Heart Control.imageset/Heart Control.png -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-24@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-24@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-44@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-44@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-86@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-86@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-98@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-98@2x.png -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-27.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaspaulmann/HeartControl/HEAD/Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon-27.5@2x.png -------------------------------------------------------------------------------- /Heart Control.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Heart Control/Heart Control.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.healthkit 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Heart Control WatchKit Extension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.healthkit 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/HeartRate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeartRate.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 07/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct HeartRate { 12 | 13 | let timestamp: Date 14 | let bpm: Double 15 | 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build generated 2 | build/ 3 | DerivedData/ 4 | 5 | # Various settings 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | 16 | # Other 17 | .DS_Store 18 | *.moved-aside 19 | *.xcuserstate 20 | 21 | # Obj-C/Swift specific 22 | *.hmap 23 | *.ipa 24 | 25 | # Playgrounds 26 | timeline.xctimeline 27 | playground.xcworkspace -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/HKUnit+BeatsPerMinute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HKUnit+BeatsPerMinute.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import HealthKit 10 | 11 | extension HKUnit { 12 | 13 | static func beatsPerMinute() -> HKUnit { 14 | return HKUnit.count().unitDivided(by: HKUnit.minute()) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Heart Control/Assets.xcassets/Heart Control.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Heart Control.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "scale" : "2x", 10 | "screen-width" : "<=145" 11 | }, 12 | { 13 | "idiom" : "watch", 14 | "scale" : "2x", 15 | "screen-width" : ">145" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "scale" : "2x", 10 | "screen-width" : "<=145" 11 | }, 12 | { 13 | "idiom" : "watch", 14 | "scale" : "2x", 15 | "screen-width" : ">145" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "scale" : "2x", 10 | "screen-width" : "<=145" 11 | }, 12 | { 13 | "idiom" : "watch", 14 | "scale" : "2x", 15 | "screen-width" : ">145" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "idiom" : "watch", 5 | "filename" : "Circular.imageset", 6 | "role" : "circular" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "filename" : "Modular.imageset", 11 | "role" : "modular" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "filename" : "Utilitarian.imageset", 16 | "role" : "utilitarian" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Heart Control/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /Heart Control/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import HealthKit 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | // MARK: - Properties 16 | 17 | private let healthStore = HKHealthStore() 18 | 19 | var window: UIWindow? 20 | 21 | // MARK: - Lifecycle 22 | 23 | private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 24 | return true 25 | } 26 | 27 | func applicationShouldRequestHealthAuthorization(_ application: UIApplication) { 28 | // Authorize access to health data for watch. 29 | healthStore.handleAuthorizationForExtension { success, error in 30 | print(success) 31 | } 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Swift](https://img.shields.io/badge/Swift-3.0-green.svg)](https://swift.org) [![watchOS](https://img.shields.io/badge/watchOS-3.0-green.svg)](https://developer.apple.com/watchos/) 2 | 3 | # Heart Control 4 | 5 | Monitor your heart rate on the apple watch - continuously and easy. 6 | 7 | ## What is it? 8 | 9 | Heart Control is a standalone watch app to monitor continuously heart rate on [watchOS 3](http://www.apple.com/watchos-preview/). It collects and analyzes data in real-time in the background. 10 | 11 | ## What is it not? 12 | 13 | It's not a whole implementation of every little detail of [Apple's HealthKit](https://developer.apple.com/healthkit/). It's more or less a quick start guide for workout apps on watchOS 3. 14 | 15 | ## Special Thanks 16 | 17 | Thanks to [Dash Brittain](http://www.roxannebrittain.com) and [Jorge Morinigo](https://www.linkedin.com/in/jorgemorinigo) for your WWDC talk [Building Great Workout Apps](https://developer.apple.com/videos/play/wwdc2016/235/). 18 | -------------------------------------------------------------------------------- /Heart Control WatchKit App/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Heart Control 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | UISupportedInterfaceOrientations 26 | 27 | UIInterfaceOrientationPortrait 28 | UIInterfaceOrientationPortraitUpsideDown 29 | 30 | WKCompanionAppBundleIdentifier 31 | com.thomaspaulmann.Heart-Control 32 | WKWatchKitApp 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Heart Control/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | healthkit 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | 38 | NSHealthShareUsageDescription 39 | Read your Heart Rate and present it on your Apple Watch. 40 | 41 | 42 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/AuthorizationManger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HKAuthorizationManger.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 07/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import HealthKit 10 | 11 | class AuthorizationManager { 12 | 13 | static func requestAuthorization(completionHandler: ((_ success: Bool) -> Void)) { 14 | // Create health store. 15 | let healthStore = HKHealthStore() 16 | 17 | // Check if there is health data available. 18 | if (!HKHealthStore.isHealthDataAvailable()) { 19 | print("No health data is available.") 20 | completionHandler(false) 21 | return 22 | } 23 | 24 | // Create quantity type for heart rate. 25 | guard let heartRateQuantityType = HKQuantityType.quantityType(forIdentifier: .heartRate) else { 26 | print("Unable to create quantity type for heart rate.") 27 | completionHandler(false) 28 | return 29 | } 30 | 31 | // Request authorization to read heart rate data. 32 | healthStore.requestAuthorization(toShare: nil, read: [heartRateQuantityType]) { (success, error) -> Void in 33 | // If there is an error, do nothing. 34 | guard error == nil else { 35 | print(error) 36 | completionHandler(false) 37 | return 38 | } 39 | 40 | // Delegate success. 41 | completionHandler(success) 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Heart Control WatchKit Extension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSExtension 26 | 27 | NSExtensionAttributes 28 | 29 | WKAppBundleIdentifier 30 | com.thomaspaulmann.Heart-Control.watchkitapp 31 | 32 | NSExtensionPointIdentifier 33 | com.apple.watchkit 34 | 35 | UIRequiredDeviceCapabilities 36 | 37 | healthkit 38 | 39 | WKBackgroundModes 40 | 41 | workout-processing 42 | 43 | WKExtensionDelegateClassName 44 | $(PRODUCT_MODULE_NAME).ExtensionDelegate 45 | 46 | 47 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/ExtensionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionDelegate.swift 3 | // Heart Control WatchKit Extension 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | 11 | class ExtensionDelegate: NSObject, WKExtensionDelegate { 12 | 13 | func applicationDidFinishLaunching() { 14 | // Perform any final initialization of your application. 15 | } 16 | 17 | func applicationDidBecomeActive() { 18 | // 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. 19 | } 20 | 21 | func applicationWillResignActive() { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, etc. 24 | } 25 | 26 | func handle(_ backgroundTasks: Set) { 27 | // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. 28 | backgroundTasks.forEach { (task) in 29 | // Process the background task 30 | 31 | // Be sure to complete each task when finished processing. 32 | task.setTaskCompleted() 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/InterfaceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.swift 3 | // Heart Control WatchKit Extension 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | 11 | class InterfaceController: WKInterfaceController { 12 | 13 | // MARK: - Outlets 14 | 15 | @IBOutlet var heartRateLabel: WKInterfaceLabel! 16 | @IBOutlet var controlButton: WKInterfaceButton! 17 | 18 | // MARK: - Properties 19 | 20 | private let workoutManager = WorkoutManager() 21 | 22 | // MARK: - Lifecycle 23 | 24 | override func willActivate() { 25 | super.willActivate() 26 | 27 | // Configure workout manager. 28 | workoutManager.delegate = self 29 | } 30 | 31 | // MARK: - Actions 32 | 33 | @IBAction func didTapButton() { 34 | switch workoutManager.state { 35 | case .started: 36 | // Stop current workout. 37 | workoutManager.stop() 38 | break 39 | case .stopped: 40 | // Start new workout. 41 | workoutManager.start() 42 | break 43 | } 44 | } 45 | 46 | } 47 | 48 | // MARK: - Workout Manager Delegate 49 | 50 | extension InterfaceController: WorkoutManagerDelegate { 51 | 52 | func workoutManager(_ manager: WorkoutManager, didChangeStateTo newState: WorkoutState) { 53 | // Update title of control button. 54 | controlButton.setTitle(newState.actionText()) 55 | } 56 | 57 | func workoutManager(_ manager: WorkoutManager, didChangeHeartRateTo newHeartRate: HeartRate) { 58 | // Update heart rate label. 59 | heartRateLabel.setText(String(format: "%.0f", newHeartRate.bpm)) 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Heart Control WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-29@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "24x24", 11 | "idiom" : "watch", 12 | "filename" : "Icon-24@2x.png", 13 | "scale" : "2x", 14 | "role" : "notificationCenter", 15 | "subtype" : "38mm" 16 | }, 17 | { 18 | "size" : "27.5x27.5", 19 | "idiom" : "watch", 20 | "filename" : "Icon-27.5@2x.png", 21 | "scale" : "2x", 22 | "role" : "notificationCenter", 23 | "subtype" : "42mm" 24 | }, 25 | { 26 | "size" : "29x29", 27 | "idiom" : "watch", 28 | "role" : "companionSettings", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "size" : "29x29", 33 | "idiom" : "watch", 34 | "filename" : "Icon-29@3x.png", 35 | "role" : "companionSettings", 36 | "scale" : "3x" 37 | }, 38 | { 39 | "size" : "40x40", 40 | "idiom" : "watch", 41 | "filename" : "Icon-40@2x.png", 42 | "scale" : "2x", 43 | "role" : "appLauncher", 44 | "subtype" : "38mm" 45 | }, 46 | { 47 | "size" : "44x44", 48 | "idiom" : "watch", 49 | "filename" : "Icon-44@2x.png", 50 | "scale" : "2x", 51 | "role" : "longLook", 52 | "subtype" : "42mm" 53 | }, 54 | { 55 | "size" : "86x86", 56 | "idiom" : "watch", 57 | "filename" : "Icon-86@2x.png", 58 | "scale" : "2x", 59 | "role" : "quickLook", 60 | "subtype" : "38mm" 61 | }, 62 | { 63 | "size" : "98x98", 64 | "idiom" : "watch", 65 | "filename" : "Icon-98@2x.png", 66 | "scale" : "2x", 67 | "role" : "quickLook", 68 | "subtype" : "42mm" 69 | } 70 | ], 71 | "info" : { 72 | "version" : 1, 73 | "author" : "xcode" 74 | } 75 | } -------------------------------------------------------------------------------- /Heart Control WatchKit App/Base.lproj/Interface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Heart Control/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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/HeartRateManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeartRateManager.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import HealthKit 10 | 11 | typealias HKQueryUpdateHandler = ((HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Swift.Void) 12 | 13 | protocol HeartRateManagerDelegate: class { 14 | 15 | func heartRate(didChangeTo newHeartRate: HeartRate) 16 | 17 | } 18 | 19 | class HeartRateManager { 20 | 21 | // MARK: - Properties 22 | 23 | private let healthStore = HKHealthStore() 24 | 25 | weak var delegate: HeartRateManagerDelegate? 26 | 27 | private var activeQueries = [HKQuery]() 28 | 29 | // MARK: - Initialization 30 | 31 | init() { 32 | // Request authorization to read heart rate data. 33 | AuthorizationManager.requestAuthorization { (success) in 34 | // TODO: Export error. 35 | print(success) 36 | } 37 | } 38 | 39 | // MARK: - Public API 40 | 41 | func start() { 42 | // Configure heart rate quantity type. 43 | guard let quantityType = HKObjectType.quantityType(forIdentifier: .heartRate) else { return } 44 | 45 | // Create query to receive continiuous heart rate samples. 46 | let datePredicate = HKQuery.predicateForSamples(withStart: Date(), end: nil, options: .strictStartDate) 47 | let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()]) 48 | let queryPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:[datePredicate, devicePredicate]) 49 | let updateHandler: HKQueryUpdateHandler = { [weak self] query, samples, deletedObjects, queryAnchor, error in 50 | if let quantitySamples = samples as? [HKQuantitySample] { 51 | self?.process(samples: quantitySamples) 52 | } 53 | } 54 | let query = HKAnchoredObjectQuery(type: quantityType, 55 | predicate: queryPredicate, 56 | anchor: nil, 57 | limit: HKObjectQueryNoLimit, 58 | resultsHandler: updateHandler) 59 | query.updateHandler = updateHandler 60 | 61 | // Execute the heart rate query. 62 | healthStore.execute(query) 63 | 64 | // Remember all active Queries to stop them later. 65 | activeQueries.append(query) 66 | } 67 | 68 | func stop() { 69 | // Stop all active queries. 70 | activeQueries.forEach { healthStore.stop($0) } 71 | activeQueries.removeAll() 72 | } 73 | 74 | // MARK: - Process 75 | 76 | private func process(samples: [HKQuantitySample]) { 77 | // Process every single sample. 78 | samples.forEach { process(sample: $0) } 79 | } 80 | 81 | private func process(sample: HKQuantitySample) { 82 | // If sample is not a heart rate sample, then do nothing. 83 | if (sample.quantityType != HKObjectType.quantityType(forIdentifier: .heartRate)) { 84 | return 85 | } 86 | 87 | // If sample is not compatible with beats per minute, then do nothing. 88 | if (!sample.quantity.is(compatibleWith: HKUnit.beatsPerMinute())) { 89 | return 90 | } 91 | 92 | // Extract information from sample. 93 | let timestamp = sample.endDate 94 | let count = sample.quantity.doubleValue(for: .beatsPerMinute()) 95 | 96 | // Delegate new heart rate. 97 | let newHeartRate = HeartRate(timestamp: timestamp, bpm: count) 98 | delegate?.heartRate(didChangeTo: newHeartRate) 99 | } 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Heart Control/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 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "Icon-App-29x29@1x.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "Icon-App-29x29@2x.png", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "idiom" : "iphone", 27 | "size" : "29x29", 28 | "scale" : "3x" 29 | }, 30 | { 31 | "idiom" : "iphone", 32 | "size" : "40x40", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "size" : "40x40", 37 | "idiom" : "iphone", 38 | "filename" : "Icon-App-40x40@3x.png", 39 | "scale" : "3x" 40 | }, 41 | { 42 | "size" : "60x60", 43 | "idiom" : "iphone", 44 | "filename" : "Icon-App-60x60@2x.png", 45 | "scale" : "2x" 46 | }, 47 | { 48 | "idiom" : "iphone", 49 | "size" : "60x60", 50 | "scale" : "3x" 51 | }, 52 | { 53 | "idiom" : "ipad", 54 | "size" : "20x20", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "idiom" : "ipad", 59 | "size" : "20x20", 60 | "scale" : "2x" 61 | }, 62 | { 63 | "idiom" : "ipad", 64 | "size" : "29x29", 65 | "scale" : "1x" 66 | }, 67 | { 68 | "idiom" : "ipad", 69 | "size" : "29x29", 70 | "scale" : "2x" 71 | }, 72 | { 73 | "size" : "40x40", 74 | "idiom" : "ipad", 75 | "filename" : "Icon-App-40x40@1x.png", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "40x40", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "size" : "76x76", 85 | "idiom" : "ipad", 86 | "filename" : "Icon-App-76x76@1x.png", 87 | "scale" : "1x" 88 | }, 89 | { 90 | "size" : "76x76", 91 | "idiom" : "ipad", 92 | "filename" : "Icon-App-76x76@2x.png", 93 | "scale" : "2x" 94 | }, 95 | { 96 | "size" : "83.5x83.5", 97 | "idiom" : "ipad", 98 | "filename" : "Icon-App-83.5x83.5@2x.png", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "idiom" : "car", 103 | "size" : "60x60", 104 | "scale" : "2x" 105 | }, 106 | { 107 | "size" : "60x60", 108 | "idiom" : "car", 109 | "filename" : "Icon-App-60x60@3x.png", 110 | "scale" : "3x" 111 | }, 112 | { 113 | "size" : "24x24", 114 | "idiom" : "watch", 115 | "scale" : "2x", 116 | "role" : "notificationCenter", 117 | "subtype" : "38mm" 118 | }, 119 | { 120 | "size" : "27.5x27.5", 121 | "idiom" : "watch", 122 | "scale" : "2x", 123 | "role" : "notificationCenter", 124 | "subtype" : "42mm" 125 | }, 126 | { 127 | "size" : "29x29", 128 | "idiom" : "watch", 129 | "role" : "companionSettings", 130 | "scale" : "2x" 131 | }, 132 | { 133 | "size" : "29x29", 134 | "idiom" : "watch", 135 | "filename" : "Icon-App-29x29@3x.png", 136 | "role" : "companionSettings", 137 | "scale" : "3x" 138 | }, 139 | { 140 | "size" : "40x40", 141 | "idiom" : "watch", 142 | "filename" : "Icon-App-40x40@2x.png", 143 | "scale" : "2x", 144 | "role" : "appLauncher", 145 | "subtype" : "38mm" 146 | }, 147 | { 148 | "size" : "44x44", 149 | "idiom" : "watch", 150 | "scale" : "2x", 151 | "role" : "longLook", 152 | "subtype" : "42mm" 153 | }, 154 | { 155 | "size" : "86x86", 156 | "idiom" : "watch", 157 | "scale" : "2x", 158 | "role" : "quickLook", 159 | "subtype" : "38mm" 160 | }, 161 | { 162 | "size" : "98x98", 163 | "idiom" : "watch", 164 | "scale" : "2x", 165 | "role" : "quickLook", 166 | "subtype" : "42mm" 167 | } 168 | ], 169 | "info" : { 170 | "version" : 1, 171 | "author" : "xcode" 172 | } 173 | } -------------------------------------------------------------------------------- /Heart Control WatchKit Extension/WorkoutManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WorkoutManager.swift 3 | // Heart Control 4 | // 5 | // Created by Thomas Paul Mann on 01/08/16. 6 | // Copyright © 2016 Thomas Paul Mann. All rights reserved. 7 | // 8 | 9 | import HealthKit 10 | 11 | enum WorkoutState { 12 | 13 | case started, stopped 14 | 15 | } 16 | 17 | extension WorkoutState { 18 | 19 | func actionText() -> String { 20 | switch self { 21 | case .started: 22 | return "Stop" 23 | case .stopped: 24 | return "Start" 25 | } 26 | } 27 | 28 | } 29 | 30 | protocol WorkoutManagerDelegate: class { 31 | 32 | func workoutManager(_ manager: WorkoutManager, didChangeStateTo newState: WorkoutState) 33 | func workoutManager(_ manager: WorkoutManager, didChangeHeartRateTo newHeartRate: HeartRate) 34 | 35 | } 36 | 37 | class WorkoutManager: NSObject { 38 | 39 | // MARK: - Properties 40 | 41 | private let healthStore = HKHealthStore() 42 | fileprivate let heartRateManager = HeartRateManager() 43 | 44 | weak var delegate: WorkoutManagerDelegate? 45 | 46 | private(set) var state: WorkoutState = .stopped 47 | 48 | private var session: HKWorkoutSession? 49 | 50 | // MARK: - Initialization 51 | 52 | override init() { 53 | super.init() 54 | 55 | // Configure heart rate manager. 56 | heartRateManager.delegate = self 57 | } 58 | 59 | // MARK: - Public API 60 | 61 | func start() { 62 | // If we have already started the workout, then do nothing. 63 | if (session != nil) { 64 | // Another workout is running. 65 | return 66 | } 67 | 68 | // Configure the workout session. 69 | let workoutConfiguration = HKWorkoutConfiguration() 70 | workoutConfiguration.activityType = .other 71 | workoutConfiguration.locationType = .indoor 72 | 73 | // Create workout session. 74 | do { 75 | session = try HKWorkoutSession(configuration: workoutConfiguration) 76 | session!.delegate = self 77 | } catch { 78 | fatalError("Unable to create Workout Session!") 79 | } 80 | 81 | // Start workout session. 82 | healthStore.start(session!) 83 | 84 | // Update state to started and inform delegates. 85 | state = .started 86 | delegate?.workoutManager(self, didChangeStateTo: state) 87 | } 88 | 89 | func stop() { 90 | // If we have already stopped the workout, then do nothing. 91 | if (session == nil) { 92 | return 93 | } 94 | 95 | // Stop querying heart rate. 96 | heartRateManager.stop() 97 | 98 | // Stop the workout session. 99 | healthStore.end(session!) 100 | 101 | // Clear the workout session. 102 | session = nil 103 | 104 | // Update state to stopped and inform delegates. 105 | state = .stopped 106 | delegate?.workoutManager(self, didChangeStateTo: state) 107 | } 108 | 109 | } 110 | 111 | // MARK: - Workout Session Delegate 112 | 113 | extension WorkoutManager: HKWorkoutSessionDelegate { 114 | 115 | func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) { 116 | switch toState { 117 | case .running: 118 | if fromState == .notStarted { 119 | heartRateManager.start() 120 | } 121 | 122 | default: 123 | break 124 | } 125 | } 126 | 127 | func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) { 128 | fatalError(error.localizedDescription) 129 | } 130 | 131 | func workoutSession(_ workoutSession: HKWorkoutSession, didGenerate event: HKWorkoutEvent) { 132 | print("Did generate \(event)") 133 | } 134 | 135 | } 136 | 137 | // MARK: - Heart Rate Delegate 138 | 139 | extension WorkoutManager: HeartRateManagerDelegate { 140 | 141 | func heartRate(didChangeTo newHeartRate: HeartRate) { 142 | delegate?.workoutManager(self, didChangeHeartRateTo: newHeartRate) 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /Heart Control/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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Heart Control.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BE25AFEB1D4F33B100DAF094 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25AFEA1D4F33B100DAF094 /* AppDelegate.swift */; }; 11 | BE25AFED1D4F33B100DAF094 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25AFEC1D4F33B100DAF094 /* ViewController.swift */; }; 12 | BE25AFF01D4F33B100DAF094 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE25AFEE1D4F33B100DAF094 /* Main.storyboard */; }; 13 | BE25AFF21D4F33B100DAF094 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE25AFF11D4F33B100DAF094 /* Assets.xcassets */; }; 14 | BE25AFF51D4F33B100DAF094 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE25AFF31D4F33B100DAF094 /* LaunchScreen.storyboard */; }; 15 | BE25AFFA1D4F33B100DAF094 /* Heart Control WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = BE25AFF91D4F33B100DAF094 /* Heart Control WatchKit App.app */; }; 16 | BE25B0001D4F33B100DAF094 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE25AFFE1D4F33B100DAF094 /* Interface.storyboard */; }; 17 | BE25B0021D4F33B100DAF094 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE25B0011D4F33B100DAF094 /* Assets.xcassets */; }; 18 | BE25B0091D4F33B100DAF094 /* Heart Control WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BE25B0081D4F33B100DAF094 /* Heart Control WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 19 | BE25B00E1D4F33B100DAF094 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25B00D1D4F33B100DAF094 /* InterfaceController.swift */; }; 20 | BE25B0101D4F33B100DAF094 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25B00F1D4F33B100DAF094 /* ExtensionDelegate.swift */; }; 21 | BE25B0121D4F33B100DAF094 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE25B0111D4F33B100DAF094 /* Assets.xcassets */; }; 22 | BE3FDBDC1D576B8D009165A8 /* HeartRate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE3FDBDB1D576B8D009165A8 /* HeartRate.swift */; }; 23 | BE496A231D4F4D9A00C82C4F /* WorkoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE496A221D4F4D9A00C82C4F /* WorkoutManager.swift */; }; 24 | BE5AEE171D4F7CED0027C49C /* HKUnit+BeatsPerMinute.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5AEE161D4F7CED0027C49C /* HKUnit+BeatsPerMinute.swift */; }; 25 | BE7070091D57A13D00E41B95 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE7070081D57A13D00E41B95 /* HealthKit.framework */; }; 26 | BE70700B1D57A14300E41B95 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE70700A1D57A14300E41B95 /* HealthKit.framework */; }; 27 | BE70700D1D57A29500E41B95 /* AuthorizationManger.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE70700C1D57A29500E41B95 /* AuthorizationManger.swift */; }; 28 | BEB5C5BB1D4F656D00BBF490 /* HeartRateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEB5C5BA1D4F656D00BBF490 /* HeartRateManager.swift */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | BE25AFFB1D4F33B100DAF094 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = BE25AFDF1D4F33B000DAF094 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = BE25AFF81D4F33B100DAF094; 37 | remoteInfo = "Heart Control WatchKit App"; 38 | }; 39 | BE25B00A1D4F33B100DAF094 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = BE25AFDF1D4F33B000DAF094 /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = BE25B0071D4F33B100DAF094; 44 | remoteInfo = "Heart Control WatchKit Extension"; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXCopyFilesBuildPhase section */ 49 | BE25B0191D4F33B100DAF094 /* Embed App Extensions */ = { 50 | isa = PBXCopyFilesBuildPhase; 51 | buildActionMask = 2147483647; 52 | dstPath = ""; 53 | dstSubfolderSpec = 13; 54 | files = ( 55 | BE25B0091D4F33B100DAF094 /* Heart Control WatchKit Extension.appex in Embed App Extensions */, 56 | ); 57 | name = "Embed App Extensions"; 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | BE25B01D1D4F33B100DAF094 /* Embed Watch Content */ = { 61 | isa = PBXCopyFilesBuildPhase; 62 | buildActionMask = 2147483647; 63 | dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; 64 | dstSubfolderSpec = 16; 65 | files = ( 66 | BE25AFFA1D4F33B100DAF094 /* Heart Control WatchKit App.app in Embed Watch Content */, 67 | ); 68 | name = "Embed Watch Content"; 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXCopyFilesBuildPhase section */ 72 | 73 | /* Begin PBXFileReference section */ 74 | BE25AFE71D4F33B100DAF094 /* Heart Control.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Heart Control.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 75 | BE25AFEA1D4F33B100DAF094 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 76 | BE25AFEC1D4F33B100DAF094 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 77 | BE25AFEF1D4F33B100DAF094 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 78 | BE25AFF11D4F33B100DAF094 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 79 | BE25AFF41D4F33B100DAF094 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 80 | BE25AFF61D4F33B100DAF094 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 81 | BE25AFF91D4F33B100DAF094 /* Heart Control WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Heart Control WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | BE25AFFF1D4F33B100DAF094 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; 83 | BE25B0011D4F33B100DAF094 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 84 | BE25B0031D4F33B100DAF094 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 85 | BE25B0081D4F33B100DAF094 /* Heart Control WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Heart Control WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 86 | BE25B00D1D4F33B100DAF094 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; }; 87 | BE25B00F1D4F33B100DAF094 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; 88 | BE25B0111D4F33B100DAF094 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 89 | BE25B0131D4F33B100DAF094 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 90 | BE3FDBDB1D576B8D009165A8 /* HeartRate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeartRate.swift; sourceTree = ""; }; 91 | BE496A1C1D4F467100C82C4F /* Heart Control WatchKit Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Heart Control WatchKit Extension.entitlements"; sourceTree = ""; }; 92 | BE496A1D1D4F467900C82C4F /* Heart Control.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Heart Control.entitlements"; sourceTree = ""; }; 93 | BE496A221D4F4D9A00C82C4F /* WorkoutManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkoutManager.swift; sourceTree = ""; }; 94 | BE5AEE161D4F7CED0027C49C /* HKUnit+BeatsPerMinute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HKUnit+BeatsPerMinute.swift"; sourceTree = ""; }; 95 | BE7070081D57A13D00E41B95 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; 96 | BE70700A1D57A14300E41B95 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/System/Library/Frameworks/HealthKit.framework; sourceTree = DEVELOPER_DIR; }; 97 | BE70700C1D57A29500E41B95 /* AuthorizationManger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationManger.swift; sourceTree = ""; }; 98 | BEB5C5BA1D4F656D00BBF490 /* HeartRateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeartRateManager.swift; sourceTree = ""; }; 99 | /* End PBXFileReference section */ 100 | 101 | /* Begin PBXFrameworksBuildPhase section */ 102 | BE25AFE41D4F33B000DAF094 /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | BE7070091D57A13D00E41B95 /* HealthKit.framework in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | BE25B0051D4F33B100DAF094 /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | BE70700B1D57A14300E41B95 /* HealthKit.framework in Frameworks */, 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | /* End PBXFrameworksBuildPhase section */ 119 | 120 | /* Begin PBXGroup section */ 121 | BE25AFDE1D4F33B000DAF094 = { 122 | isa = PBXGroup; 123 | children = ( 124 | BE25AFE91D4F33B100DAF094 /* Heart Control */, 125 | BE25AFFD1D4F33B100DAF094 /* Heart Control WatchKit App */, 126 | BE25B00C1D4F33B100DAF094 /* Heart Control WatchKit Extension */, 127 | BE25AFE81D4F33B100DAF094 /* Products */, 128 | BE496A191D4F467100C82C4F /* Frameworks */, 129 | ); 130 | sourceTree = ""; 131 | }; 132 | BE25AFE81D4F33B100DAF094 /* Products */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | BE25AFE71D4F33B100DAF094 /* Heart Control.app */, 136 | BE25AFF91D4F33B100DAF094 /* Heart Control WatchKit App.app */, 137 | BE25B0081D4F33B100DAF094 /* Heart Control WatchKit Extension.appex */, 138 | ); 139 | name = Products; 140 | sourceTree = ""; 141 | }; 142 | BE25AFE91D4F33B100DAF094 /* Heart Control */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | BE3FDBDE1D576BC1009165A8 /* Supporting Files */, 146 | BE25AFEA1D4F33B100DAF094 /* AppDelegate.swift */, 147 | BE25AFEC1D4F33B100DAF094 /* ViewController.swift */, 148 | BE25AFEE1D4F33B100DAF094 /* Main.storyboard */, 149 | BE25AFF31D4F33B100DAF094 /* LaunchScreen.storyboard */, 150 | ); 151 | path = "Heart Control"; 152 | sourceTree = ""; 153 | }; 154 | BE25AFFD1D4F33B100DAF094 /* Heart Control WatchKit App */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | BE3FDBDF1D578CFE009165A8 /* Supporting Files */, 158 | BE25AFFE1D4F33B100DAF094 /* Interface.storyboard */, 159 | ); 160 | path = "Heart Control WatchKit App"; 161 | sourceTree = ""; 162 | }; 163 | BE25B00C1D4F33B100DAF094 /* Heart Control WatchKit Extension */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | BE3FDBDD1D576BB1009165A8 /* Supporting Files */, 167 | BE25B00D1D4F33B100DAF094 /* InterfaceController.swift */, 168 | BE25B00F1D4F33B100DAF094 /* ExtensionDelegate.swift */, 169 | BE496A221D4F4D9A00C82C4F /* WorkoutManager.swift */, 170 | BEB5C5BA1D4F656D00BBF490 /* HeartRateManager.swift */, 171 | BE70700C1D57A29500E41B95 /* AuthorizationManger.swift */, 172 | BE3FDBDB1D576B8D009165A8 /* HeartRate.swift */, 173 | BE5AEE161D4F7CED0027C49C /* HKUnit+BeatsPerMinute.swift */, 174 | ); 175 | path = "Heart Control WatchKit Extension"; 176 | sourceTree = ""; 177 | }; 178 | BE3FDBDD1D576BB1009165A8 /* Supporting Files */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | BE496A1C1D4F467100C82C4F /* Heart Control WatchKit Extension.entitlements */, 182 | BE25B0111D4F33B100DAF094 /* Assets.xcassets */, 183 | BE25B0131D4F33B100DAF094 /* Info.plist */, 184 | ); 185 | name = "Supporting Files"; 186 | sourceTree = ""; 187 | }; 188 | BE3FDBDE1D576BC1009165A8 /* Supporting Files */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | BE496A1D1D4F467900C82C4F /* Heart Control.entitlements */, 192 | BE25AFF11D4F33B100DAF094 /* Assets.xcassets */, 193 | BE25AFF61D4F33B100DAF094 /* Info.plist */, 194 | ); 195 | name = "Supporting Files"; 196 | sourceTree = ""; 197 | }; 198 | BE3FDBDF1D578CFE009165A8 /* Supporting Files */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | BE25B0011D4F33B100DAF094 /* Assets.xcassets */, 202 | BE25B0031D4F33B100DAF094 /* Info.plist */, 203 | ); 204 | name = "Supporting Files"; 205 | sourceTree = ""; 206 | }; 207 | BE496A191D4F467100C82C4F /* Frameworks */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | BE70700A1D57A14300E41B95 /* HealthKit.framework */, 211 | BE7070081D57A13D00E41B95 /* HealthKit.framework */, 212 | ); 213 | name = Frameworks; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXGroup section */ 217 | 218 | /* Begin PBXNativeTarget section */ 219 | BE25AFE61D4F33B000DAF094 /* Heart Control */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = BE25B01E1D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control" */; 222 | buildPhases = ( 223 | BE25AFE31D4F33B000DAF094 /* Sources */, 224 | BE25AFE41D4F33B000DAF094 /* Frameworks */, 225 | BE25AFE51D4F33B000DAF094 /* Resources */, 226 | BE25B01D1D4F33B100DAF094 /* Embed Watch Content */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | BE25AFFC1D4F33B100DAF094 /* PBXTargetDependency */, 232 | ); 233 | name = "Heart Control"; 234 | productName = "Heart Control"; 235 | productReference = BE25AFE71D4F33B100DAF094 /* Heart Control.app */; 236 | productType = "com.apple.product-type.application"; 237 | }; 238 | BE25AFF81D4F33B100DAF094 /* Heart Control WatchKit App */ = { 239 | isa = PBXNativeTarget; 240 | buildConfigurationList = BE25B01A1D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control WatchKit App" */; 241 | buildPhases = ( 242 | BE25AFF71D4F33B100DAF094 /* Resources */, 243 | BE25B0191D4F33B100DAF094 /* Embed App Extensions */, 244 | ); 245 | buildRules = ( 246 | ); 247 | dependencies = ( 248 | BE25B00B1D4F33B100DAF094 /* PBXTargetDependency */, 249 | ); 250 | name = "Heart Control WatchKit App"; 251 | productName = "Heart Control WatchKit App"; 252 | productReference = BE25AFF91D4F33B100DAF094 /* Heart Control WatchKit App.app */; 253 | productType = "com.apple.product-type.application.watchapp2"; 254 | }; 255 | BE25B0071D4F33B100DAF094 /* Heart Control WatchKit Extension */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = BE25B0161D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control WatchKit Extension" */; 258 | buildPhases = ( 259 | BE25B0041D4F33B100DAF094 /* Sources */, 260 | BE25B0051D4F33B100DAF094 /* Frameworks */, 261 | BE25B0061D4F33B100DAF094 /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | ); 267 | name = "Heart Control WatchKit Extension"; 268 | productName = "Heart Control WatchKit Extension"; 269 | productReference = BE25B0081D4F33B100DAF094 /* Heart Control WatchKit Extension.appex */; 270 | productType = "com.apple.product-type.watchkit2-extension"; 271 | }; 272 | /* End PBXNativeTarget section */ 273 | 274 | /* Begin PBXProject section */ 275 | BE25AFDF1D4F33B000DAF094 /* Project object */ = { 276 | isa = PBXProject; 277 | attributes = { 278 | LastSwiftUpdateCheck = 0800; 279 | LastUpgradeCheck = 0800; 280 | ORGANIZATIONNAME = "Thomas Paul Mann"; 281 | TargetAttributes = { 282 | BE25AFE61D4F33B000DAF094 = { 283 | CreatedOnToolsVersion = 8.0; 284 | DevelopmentTeam = E6HN743D3A; 285 | DevelopmentTeamName = "Thomas Mann"; 286 | ProvisioningStyle = Automatic; 287 | SystemCapabilities = { 288 | com.apple.HealthKit = { 289 | enabled = 1; 290 | }; 291 | }; 292 | }; 293 | BE25AFF81D4F33B100DAF094 = { 294 | CreatedOnToolsVersion = 8.0; 295 | DevelopmentTeam = E6HN743D3A; 296 | DevelopmentTeamName = "Thomas Mann"; 297 | ProvisioningStyle = Automatic; 298 | }; 299 | BE25B0071D4F33B100DAF094 = { 300 | CreatedOnToolsVersion = 8.0; 301 | DevelopmentTeam = E6HN743D3A; 302 | DevelopmentTeamName = "Thomas Mann"; 303 | ProvisioningStyle = Automatic; 304 | SystemCapabilities = { 305 | com.apple.HealthKit = { 306 | enabled = 1; 307 | }; 308 | com.apple.HealthKit.watchos = { 309 | enabled = 1; 310 | }; 311 | }; 312 | }; 313 | }; 314 | }; 315 | buildConfigurationList = BE25AFE21D4F33B000DAF094 /* Build configuration list for PBXProject "Heart Control" */; 316 | compatibilityVersion = "Xcode 3.2"; 317 | developmentRegion = English; 318 | hasScannedForEncodings = 0; 319 | knownRegions = ( 320 | en, 321 | Base, 322 | ); 323 | mainGroup = BE25AFDE1D4F33B000DAF094; 324 | productRefGroup = BE25AFE81D4F33B100DAF094 /* Products */; 325 | projectDirPath = ""; 326 | projectRoot = ""; 327 | targets = ( 328 | BE25AFE61D4F33B000DAF094 /* Heart Control */, 329 | BE25AFF81D4F33B100DAF094 /* Heart Control WatchKit App */, 330 | BE25B0071D4F33B100DAF094 /* Heart Control WatchKit Extension */, 331 | ); 332 | }; 333 | /* End PBXProject section */ 334 | 335 | /* Begin PBXResourcesBuildPhase section */ 336 | BE25AFE51D4F33B000DAF094 /* Resources */ = { 337 | isa = PBXResourcesBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | BE25AFF51D4F33B100DAF094 /* LaunchScreen.storyboard in Resources */, 341 | BE25AFF21D4F33B100DAF094 /* Assets.xcassets in Resources */, 342 | BE25AFF01D4F33B100DAF094 /* Main.storyboard in Resources */, 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | }; 346 | BE25AFF71D4F33B100DAF094 /* Resources */ = { 347 | isa = PBXResourcesBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | BE25B0021D4F33B100DAF094 /* Assets.xcassets in Resources */, 351 | BE25B0001D4F33B100DAF094 /* Interface.storyboard in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | BE25B0061D4F33B100DAF094 /* Resources */ = { 356 | isa = PBXResourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | BE25B0121D4F33B100DAF094 /* Assets.xcassets in Resources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | /* End PBXResourcesBuildPhase section */ 364 | 365 | /* Begin PBXSourcesBuildPhase section */ 366 | BE25AFE31D4F33B000DAF094 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | BE25AFED1D4F33B100DAF094 /* ViewController.swift in Sources */, 371 | BE25AFEB1D4F33B100DAF094 /* AppDelegate.swift in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | BE25B0041D4F33B100DAF094 /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | BE25B0101D4F33B100DAF094 /* ExtensionDelegate.swift in Sources */, 380 | BE496A231D4F4D9A00C82C4F /* WorkoutManager.swift in Sources */, 381 | BE5AEE171D4F7CED0027C49C /* HKUnit+BeatsPerMinute.swift in Sources */, 382 | BE25B00E1D4F33B100DAF094 /* InterfaceController.swift in Sources */, 383 | BE3FDBDC1D576B8D009165A8 /* HeartRate.swift in Sources */, 384 | BE70700D1D57A29500E41B95 /* AuthorizationManger.swift in Sources */, 385 | BEB5C5BB1D4F656D00BBF490 /* HeartRateManager.swift in Sources */, 386 | ); 387 | runOnlyForDeploymentPostprocessing = 0; 388 | }; 389 | /* End PBXSourcesBuildPhase section */ 390 | 391 | /* Begin PBXTargetDependency section */ 392 | BE25AFFC1D4F33B100DAF094 /* PBXTargetDependency */ = { 393 | isa = PBXTargetDependency; 394 | target = BE25AFF81D4F33B100DAF094 /* Heart Control WatchKit App */; 395 | targetProxy = BE25AFFB1D4F33B100DAF094 /* PBXContainerItemProxy */; 396 | }; 397 | BE25B00B1D4F33B100DAF094 /* PBXTargetDependency */ = { 398 | isa = PBXTargetDependency; 399 | target = BE25B0071D4F33B100DAF094 /* Heart Control WatchKit Extension */; 400 | targetProxy = BE25B00A1D4F33B100DAF094 /* PBXContainerItemProxy */; 401 | }; 402 | /* End PBXTargetDependency section */ 403 | 404 | /* Begin PBXVariantGroup section */ 405 | BE25AFEE1D4F33B100DAF094 /* Main.storyboard */ = { 406 | isa = PBXVariantGroup; 407 | children = ( 408 | BE25AFEF1D4F33B100DAF094 /* Base */, 409 | ); 410 | name = Main.storyboard; 411 | sourceTree = ""; 412 | }; 413 | BE25AFF31D4F33B100DAF094 /* LaunchScreen.storyboard */ = { 414 | isa = PBXVariantGroup; 415 | children = ( 416 | BE25AFF41D4F33B100DAF094 /* Base */, 417 | ); 418 | name = LaunchScreen.storyboard; 419 | sourceTree = ""; 420 | }; 421 | BE25AFFE1D4F33B100DAF094 /* Interface.storyboard */ = { 422 | isa = PBXVariantGroup; 423 | children = ( 424 | BE25AFFF1D4F33B100DAF094 /* Base */, 425 | ); 426 | name = Interface.storyboard; 427 | sourceTree = ""; 428 | }; 429 | /* End PBXVariantGroup section */ 430 | 431 | /* Begin XCBuildConfiguration section */ 432 | BE25B0141D4F33B100DAF094 /* Debug */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ALWAYS_SEARCH_USER_PATHS = NO; 436 | CLANG_ANALYZER_NONNULL = YES; 437 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 438 | CLANG_CXX_LIBRARY = "libc++"; 439 | CLANG_ENABLE_MODULES = YES; 440 | CLANG_ENABLE_OBJC_ARC = YES; 441 | CLANG_WARN_BOOL_CONVERSION = YES; 442 | CLANG_WARN_CONSTANT_CONVERSION = YES; 443 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 444 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 449 | CLANG_WARN_UNREACHABLE_CODE = YES; 450 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 451 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 452 | COPY_PHASE_STRIP = NO; 453 | DEBUG_INFORMATION_FORMAT = dwarf; 454 | ENABLE_STRICT_OBJC_MSGSEND = YES; 455 | ENABLE_TESTABILITY = YES; 456 | GCC_C_LANGUAGE_STANDARD = gnu99; 457 | GCC_DYNAMIC_NO_PIC = NO; 458 | GCC_NO_COMMON_BLOCKS = YES; 459 | GCC_OPTIMIZATION_LEVEL = 0; 460 | GCC_PREPROCESSOR_DEFINITIONS = ( 461 | "DEBUG=1", 462 | "$(inherited)", 463 | ); 464 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 465 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 466 | GCC_WARN_UNDECLARED_SELECTOR = YES; 467 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 468 | GCC_WARN_UNUSED_FUNCTION = YES; 469 | GCC_WARN_UNUSED_VARIABLE = YES; 470 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 471 | MTL_ENABLE_DEBUG_INFO = YES; 472 | ONLY_ACTIVE_ARCH = YES; 473 | SDKROOT = iphoneos; 474 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 475 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 476 | }; 477 | name = Debug; 478 | }; 479 | BE25B0151D4F33B100DAF094 /* Release */ = { 480 | isa = XCBuildConfiguration; 481 | buildSettings = { 482 | ALWAYS_SEARCH_USER_PATHS = NO; 483 | CLANG_ANALYZER_NONNULL = YES; 484 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 485 | CLANG_CXX_LIBRARY = "libc++"; 486 | CLANG_ENABLE_MODULES = YES; 487 | CLANG_ENABLE_OBJC_ARC = YES; 488 | CLANG_WARN_BOOL_CONVERSION = YES; 489 | CLANG_WARN_CONSTANT_CONVERSION = YES; 490 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 491 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 492 | CLANG_WARN_EMPTY_BODY = YES; 493 | CLANG_WARN_ENUM_CONVERSION = YES; 494 | CLANG_WARN_INT_CONVERSION = YES; 495 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 496 | CLANG_WARN_UNREACHABLE_CODE = YES; 497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 499 | COPY_PHASE_STRIP = NO; 500 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 501 | ENABLE_NS_ASSERTIONS = NO; 502 | ENABLE_STRICT_OBJC_MSGSEND = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_NO_COMMON_BLOCKS = YES; 505 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 506 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 507 | GCC_WARN_UNDECLARED_SELECTOR = YES; 508 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 509 | GCC_WARN_UNUSED_FUNCTION = YES; 510 | GCC_WARN_UNUSED_VARIABLE = YES; 511 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 512 | MTL_ENABLE_DEBUG_INFO = NO; 513 | SDKROOT = iphoneos; 514 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 515 | VALIDATE_PRODUCT = YES; 516 | }; 517 | name = Release; 518 | }; 519 | BE25B0171D4F33B100DAF094 /* Debug */ = { 520 | isa = XCBuildConfiguration; 521 | buildSettings = { 522 | ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; 523 | CODE_SIGN_ENTITLEMENTS = "Heart Control WatchKit Extension/Heart Control WatchKit Extension.entitlements"; 524 | INFOPLIST_FILE = "Heart Control WatchKit Extension/Info.plist"; 525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 526 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control.watchkitapp.watchkitextension"; 527 | PRODUCT_NAME = "${TARGET_NAME}"; 528 | SDKROOT = watchos; 529 | SKIP_INSTALL = YES; 530 | SWIFT_VERSION = 3.0; 531 | TARGETED_DEVICE_FAMILY = 4; 532 | WATCHOS_DEPLOYMENT_TARGET = 3.0; 533 | }; 534 | name = Debug; 535 | }; 536 | BE25B0181D4F33B100DAF094 /* Release */ = { 537 | isa = XCBuildConfiguration; 538 | buildSettings = { 539 | ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; 540 | CODE_SIGN_ENTITLEMENTS = "Heart Control WatchKit Extension/Heart Control WatchKit Extension.entitlements"; 541 | INFOPLIST_FILE = "Heart Control WatchKit Extension/Info.plist"; 542 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 543 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control.watchkitapp.watchkitextension"; 544 | PRODUCT_NAME = "${TARGET_NAME}"; 545 | SDKROOT = watchos; 546 | SKIP_INSTALL = YES; 547 | SWIFT_VERSION = 3.0; 548 | TARGETED_DEVICE_FAMILY = 4; 549 | WATCHOS_DEPLOYMENT_TARGET = 3.0; 550 | }; 551 | name = Release; 552 | }; 553 | BE25B01B1D4F33B100DAF094 /* Debug */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 557 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 558 | IBSC_MODULE = Heart_Control_WatchKit_Extension; 559 | INFOPLIST_FILE = "Heart Control WatchKit App/Info.plist"; 560 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control.watchkitapp"; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | SDKROOT = watchos; 563 | SKIP_INSTALL = YES; 564 | SWIFT_VERSION = 3.0; 565 | TARGETED_DEVICE_FAMILY = 4; 566 | WATCHOS_DEPLOYMENT_TARGET = 3.0; 567 | }; 568 | name = Debug; 569 | }; 570 | BE25B01C1D4F33B100DAF094 /* Release */ = { 571 | isa = XCBuildConfiguration; 572 | buildSettings = { 573 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 574 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 575 | IBSC_MODULE = Heart_Control_WatchKit_Extension; 576 | INFOPLIST_FILE = "Heart Control WatchKit App/Info.plist"; 577 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control.watchkitapp"; 578 | PRODUCT_NAME = "$(TARGET_NAME)"; 579 | SDKROOT = watchos; 580 | SKIP_INSTALL = YES; 581 | SWIFT_VERSION = 3.0; 582 | TARGETED_DEVICE_FAMILY = 4; 583 | WATCHOS_DEPLOYMENT_TARGET = 3.0; 584 | }; 585 | name = Release; 586 | }; 587 | BE25B01F1D4F33B100DAF094 /* Debug */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 591 | CODE_SIGN_ENTITLEMENTS = "Heart Control/Heart Control.entitlements"; 592 | INFOPLIST_FILE = "Heart Control/Info.plist"; 593 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 594 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control"; 595 | PRODUCT_NAME = "$(TARGET_NAME)"; 596 | SWIFT_VERSION = 3.0; 597 | }; 598 | name = Debug; 599 | }; 600 | BE25B0201D4F33B100DAF094 /* Release */ = { 601 | isa = XCBuildConfiguration; 602 | buildSettings = { 603 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 604 | CODE_SIGN_ENTITLEMENTS = "Heart Control/Heart Control.entitlements"; 605 | INFOPLIST_FILE = "Heart Control/Info.plist"; 606 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 607 | PRODUCT_BUNDLE_IDENTIFIER = "com.thomaspaulmann.Heart-Control"; 608 | PRODUCT_NAME = "$(TARGET_NAME)"; 609 | SWIFT_VERSION = 3.0; 610 | }; 611 | name = Release; 612 | }; 613 | /* End XCBuildConfiguration section */ 614 | 615 | /* Begin XCConfigurationList section */ 616 | BE25AFE21D4F33B000DAF094 /* Build configuration list for PBXProject "Heart Control" */ = { 617 | isa = XCConfigurationList; 618 | buildConfigurations = ( 619 | BE25B0141D4F33B100DAF094 /* Debug */, 620 | BE25B0151D4F33B100DAF094 /* Release */, 621 | ); 622 | defaultConfigurationIsVisible = 0; 623 | defaultConfigurationName = Release; 624 | }; 625 | BE25B0161D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control WatchKit Extension" */ = { 626 | isa = XCConfigurationList; 627 | buildConfigurations = ( 628 | BE25B0171D4F33B100DAF094 /* Debug */, 629 | BE25B0181D4F33B100DAF094 /* Release */, 630 | ); 631 | defaultConfigurationIsVisible = 0; 632 | defaultConfigurationName = Release; 633 | }; 634 | BE25B01A1D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control WatchKit App" */ = { 635 | isa = XCConfigurationList; 636 | buildConfigurations = ( 637 | BE25B01B1D4F33B100DAF094 /* Debug */, 638 | BE25B01C1D4F33B100DAF094 /* Release */, 639 | ); 640 | defaultConfigurationIsVisible = 0; 641 | defaultConfigurationName = Release; 642 | }; 643 | BE25B01E1D4F33B100DAF094 /* Build configuration list for PBXNativeTarget "Heart Control" */ = { 644 | isa = XCConfigurationList; 645 | buildConfigurations = ( 646 | BE25B01F1D4F33B100DAF094 /* Debug */, 647 | BE25B0201D4F33B100DAF094 /* Release */, 648 | ); 649 | defaultConfigurationIsVisible = 0; 650 | defaultConfigurationName = Release; 651 | }; 652 | /* End XCConfigurationList section */ 653 | }; 654 | rootObject = BE25AFDF1D4F33B000DAF094 /* Project object */; 655 | } 656 | --------------------------------------------------------------------------------