Swift2 watchOS 2的仅心率监视器应用程序可记录额外热量并显示运动情况
基本上,我正在开发一个睡眠监测应用程序,它也可以监测心率。所以,我不想开始任何锻炼活动,但我认为这就是苹果的工作方式 以下是我正在使用的唯一心率代码:Swift2 watchOS 2的仅心率监视器应用程序可记录额外热量并显示运动情况,swift2,watchos-2,healthkit,Swift2,Watchos 2,Healthkit,基本上,我正在开发一个睡眠监测应用程序,它也可以监测心率。所以,我不想开始任何锻炼活动,但我认为这就是苹果的工作方式 以下是我正在使用的唯一心率代码: @IBOutlet private weak var label: WKInterfaceLabel! @IBOutlet private weak var deviceLabel : WKInterfaceLabel! @IBOutlet private weak var heart: WKInterfaceImage! @IBOutlet p
@IBOutlet private weak var label: WKInterfaceLabel!
@IBOutlet private weak var deviceLabel : WKInterfaceLabel!
@IBOutlet private weak var heart: WKInterfaceImage!
@IBOutlet private weak var startStopButton : WKInterfaceButton!
let healthStore = HKHealthStore()
//State of the app - is the workout activated
var workoutActive = false
// define the activity type and location
var workoutSession : HKWorkoutSession?
let heartRateUnit = HKUnit(fromString: "count/min")
var anchor = HKQueryAnchor(fromValue: Int(HKAnchoredObjectQueryNoAnchor))
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}
override func willActivate() {
super.willActivate()
guard HKHealthStore.isHealthDataAvailable() == true else {
label.setText("not available")
return
}
guard let quantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) else {
displayNotAllowed()
return
}
let dataTypes = Set(arrayLiteral: quantityType)
healthStore.requestAuthorizationToShareTypes(nil, readTypes: dataTypes) { (success, error) -> Void in
if success == false {
self.displayNotAllowed()
}
}
}
func displayNotAllowed() {
label.setText("not allowed")
}
func workoutSession(workoutSession: HKWorkoutSession, didChangeToState toState: HKWorkoutSessionState, fromState: HKWorkoutSessionState, date: NSDate) {
switch toState {
case .Running:
workoutDidStart(date)
case .Ended:
workoutDidEnd(date)
default:
print("Unexpected state \(toState)")
}
}
func workoutSession(workoutSession: HKWorkoutSession, didFailWithError error: NSError) {
// Do nothing for now
NSLog("Workout error: \(error.userInfo)")
}
func workoutDidStart(date : NSDate) {
if let query = createHeartRateStreamingQuery(date) {
healthStore.executeQuery(query)
} else {
label.setText("cannot start")
}
}
func workoutDidEnd(date : NSDate) {
if let query = createHeartRateStreamingQuery(date) {
healthStore.stopQuery(query)
label.setText("---")
} else {
label.setText("cannot stop")
}
}
// MARK: - Actions
@IBAction func startBtnTapped() {
if (self.workoutActive) {
//finish the current workout
self.workoutActive = false
self.startStopButton.setTitle("Start")
if let workout = self.workoutSession {
healthStore.endWorkoutSession(workout)
}
} else {
//start a new workout
self.workoutActive = true
self.startStopButton.setTitle("Stop")
startWorkout()
}
}
func startWorkout() {
self.workoutSession = HKWorkoutSession(activityType: HKWorkoutActivityType.CrossTraining, locationType: HKWorkoutSessionLocationType.Indoor)
self.workoutSession?.delegate = self
healthStore.startWorkoutSession(self.workoutSession!)
}
func createHeartRateStreamingQuery(workoutStartDate: NSDate) -> HKQuery? {
// adding predicate will not work
// let predicate = HKQuery.predicateForSamplesWithStartDate(workoutStartDate, endDate: nil, options: HKQueryOptions.None)
guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) else { return nil }
let heartRateQuery = HKAnchoredObjectQuery(type: quantityType, predicate: nil, anchor: anchor, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in
guard let newAnchor = newAnchor else {return}
self.anchor = newAnchor
self.updateHeartRate(sampleObjects)
}
heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in
self.anchor = newAnchor!
self.updateHeartRate(samples)
}
return heartRateQuery
}
func updateHeartRate(samples: [HKSample]?) {
guard let heartRateSamples = samples as? [HKQuantitySample] else {return}
dispatch_async(dispatch_get_main_queue()) {
guard let sample = heartRateSamples.first else{return}
let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
self.label.setText(String(UInt16(value)))
// retrieve source from sample
let name = sample.sourceRevision.source.name
self.updateDeviceName(name)
self.animateHeart()
}
}
func updateDeviceName(deviceName: String) {
deviceLabel.setText(deviceName)
}
func animateHeart() {
self.animateWithDuration(0.5) {
self.heart.setWidth(60)
self.heart.setHeight(90)
}
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * double_t(NSEC_PER_SEC)))
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_after(when, queue) {
dispatch_async(dispatch_get_main_queue(), {
self.animateWithDuration(0.5, animations: {
self.heart.setWidth(50)
self.heart.setHeight(80)
})
})
}
} }
总而言之,意外观察结果如下:
1.我监测心率的时间会影响活动应用程序中的绿色环。
2.正在记录意外的高热量,即当患者躺在床上或睡着时
请您提供正确的代码,帮助我在睡眠期间定期监测和显示一个人的心跳,而不影响绿环或额外的CAL
提前多谢 开始锻炼并运行心率监视器将在大约6小时后耗尽apple watch的电池电量(如果它充满电的话),因此让它在睡觉时连续运行在这个时候可能是不现实的 据我所知,使用workoutSession开始训练对你的应用程序来说有两件事。它让你的应用程序处于前台,每隔几秒钟就开始采集心率样本。你考虑过不开始吗?您的健康套件查询仍将按原样工作,心率监视器仍会每隔15分钟左右记录用户的心率。你最主要的事情就是把你的应用程序放在前台,我想知道你是否需要这样做(因为用户会睡着) 要从healthkit检索最后一个心率样本,请执行以下操作:
func getLatestHeartRate() {
let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
let sampleQuery = HKSampleQuery(sampleType: quantityType, predicate: nil, limit: 1, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
}
self.healthStore.executeQuery(sampleQuery)
}
谢谢你的回复。是否可以从will activate(将激活)功能上的健康应用程序检索上次记录的心率,即当用户再次打开应用程序时?另外,如果应用程序不在前台,全局调度队列会死吗?我也记下了睡觉的时间,所以也需要这些数据!要从health kit获取上一次记录的心率值,您可以创建查询,在查询中按创建日期降序对心率进行排序,然后让它仅返回第一项。全局调度队列和睡眠日期不应该消失-应用程序在后台被挂起,但不会消失,因此当它再次被带到前台时,内存会被保留。