我当前正在使用以下方法在后台获取HealthKit数据,然后将其保存到解析服务器并向用户发送通知。我遇到的问题是,它并不总是触发。如果该应用已关闭或处于非活动状态,则不会调用它,并且仅在最近打开该应用并记录了锻炼情况时才起作用(这也不是100%可靠的)。有什么想法为什么不总是这样?
方法在应用程序委托中被调用
func startObservingNewWorkouts() {
let currentUser = PFUser.current()
if currentUser != nil {
let query = PFQuery(className:"UserData")
query.whereKey("Username", equalTo:currentUser!.username!)
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if let error = error {
// Log details of the failure
print(error.localizedDescription)
} else if let objects = objects {
for object in objects {
UserData = object
let sampleType = HKObjectType.workoutType()
self.healthKitStore.enableBackgroundDelivery(for: sampleType, frequency: .immediate) { (success, error) in
if let unwrappedError = error {
print("could not enable background delivery: \(unwrappedError)")
}
if success {
print("background delivery enabled")
}
}
let query = HKObserverQuery(sampleType: sampleType, predicate: nil) { (query, completionHandler, error) in
self.updateWorkouts() {
completionHandler()
}
}
healthStore.execute(query)
}
}
}
}
}
func updateWorkouts(completionHandler: @escaping () -> Void) {
var anchor: HKQueryAnchor?
let sampleType = HKObjectType.workoutType()
let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: nil, anchor: anchor, limit: HKObjectQueryNoLimit) { [unowned self] query, newSamples, deletedSamples, newAnchor, error in
self.handleNewWorkouts(new: newSamples!, deleted: deletedSamples!)
anchor = newAnchor
completionHandler()
}
healthStore.execute(anchoredQuery)
}
func handleNewWorkouts(new: [HKSample], deleted: [HKDeletedObject]) {
print("new sample added = \(new.last?.startDate)")
userWorkouts = UserData["UserWorkouts"] as? [Dictionary<String,String>] ?? []
let i = new.last as! HKWorkout
var userWorkout = [String: String]()
userWorkout["Description"] = i.description
userWorkout["Source"] = i.sourceRevision.source.name
userWorkout["Duration"] = String(format: "%.0f", i.duration)
userWorkouts.insert(userWorkout, at: 0)
UserData["UserWorkouts"] = userWorkouts
UserData.saveInBackground {
(success: Bool, error: Error?) in
if (success) {
self.userDefaults.set(userWorkouts2, forKey: "userWorkouts")
self.userDefaults.set(Date(),forKey: "lastWorkoutUpdate")
let content = UNMutableNotificationContent()
content.title = "New Workout Logged!"
content.body = "New workout logged from \(i.sourceRevision.source.name)
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false)
let request = UNNotificationRequest(identifier: "notification.id.01", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
}