How can I read and display the workout data like in Apple Fitness? [closed] - ios

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 days ago.
Improve this question
I'm looking to display the workouts performed similar to what Apple Fitness displays. However, I want to get traditional strength training and functional strength training workouts particularly. I would also like to get the number of workouts performed within the week. I'm having issues reading the data and displaying it. Below is the code I'm using. I'm omitting the authorization method because I have that with other health variables I'm getting. Also, when I try to get the workoutActivity type to display, nothing is showing up. I've looked over apple's healthkit documentation but getting a big confused/lost as a beginner, particularly with the workout data. I've attached pictures as a reference on what I would like to accomplish
.
class HealthStoreViewModel: ObservableObject {
var selectedWorkoutQuery: HKQuery?
#Published var muscleStrength: [HKWorkout] = [HKWorkout]()
func getStrengthTrainingWorkouts() {
let date = Date()
let startDate = Calendar.current.dateInterval(of: .weekOfYear, for: date)?.start
let datePredicate = HKQuery.predicateForSamples(withStart: startDate, end: nil, options: .strictStartDate)
let traditionalStrengthTrainingPredicate = HKQuery.predicateForWorkouts(with: .traditionalStrengthTraining)
let functionalStrengthTrainingPredicate = HKQuery.predicateForWorkouts(with: .functionalStrengthTraining)
let strengthCompound = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, traditionalStrengthTrainingPredicate, functionalStrengthTrainingPredicate])
let selectedWorkoutQuery = HKSampleQuery(sampleType: HKWorkoutType.workoutType(), predicate: strengthCompound, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { strengthQuery, samples, error in
guard let samples = samples else {
fatalError("An error has occured \(error?.localizedDescription)")
}
DispatchQueue.main.async {
if let workouts = samples as? [HKWorkout] {
for workout in workouts {
self.muscleStrength.append(workout)
}
}
}
}
self.healthStore?.execute(selectedWorkoutQuery)
}
Here is the view I would like to display the count and workouts but nothing is showing
struct MuscleView: View {
#ObservedObject var healthStoreVM: HealthStoreViewModel
var body: some View {
List(healthStoreVM.muscleStrength, id: \.self) {
workout in
Text("\(workout.workoutActivityType.rawValue)")
}
}
}

Related

Unable to read workout data in healthkit in SwiftUI

I'm trying to get the number of workouts performed within the week and display the count in a view and also display the workout like you see in the Apple Fitness app. I'm having issues reading the data and displaying it. I'm trying to only get functional strength training and traditional strength training workouts. Below is the code I'm using. I'm omitting the authorization method because I have that with other health variables I'm getting. Also, when I try to get the workoutActivity type to display, nothing is showing up. I've looked over apple's healthkit documentation but getting a big confused/lost as a beginner, particularly with the workout data. Any help would be appreciated
class HealthStoreViewModel: ObservableObject {
var selectedWorkoutQuery: HKQuery?
#Published var muscleStrength: [HKWorkout] = [HKWorkout]()
func getStrengthTrainingWorkouts() {
let date = Date()
let startDate = Calendar.current.dateInterval(of: .weekOfYear, for: date)?.start
let datePredicate = HKQuery.predicateForSamples(withStart: startDate, end: nil, options: .strictStartDate)
let traditionalStrengthTrainingPredicate = HKQuery.predicateForWorkouts(with: .traditionalStrengthTraining)
let functionalStrengthTrainingPredicate = HKQuery.predicateForWorkouts(with: .functionalStrengthTraining)
let strengthCompound = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, traditionalStrengthTrainingPredicate, functionalStrengthTrainingPredicate])
let selectedWorkoutQuery = HKSampleQuery(sampleType: HKWorkoutType.workoutType(), predicate: strengthCompound, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { strengthQuery, samples, error in
guard let samples = samples else {
fatalError("An error has occured \(error?.localizedDescription)")
}
DispatchQueue.main.async {
if let workouts = samples as? [HKWorkout] {
for workout in workouts {
self.muscleStrength.append(workout)
}
}
}
}
self.healthStore?.execute(selectedWorkoutQuery)
}
Here is the view I would like to display the count and workouts but nothing is showing
struct MuscleView: View {
#ObservedObject var healthStoreVM: HealthStoreViewModel
var body: some View {
List(healthStoreVM.muscleStrength, id: \.self) {
workout in
Text("\(workout.workoutActivityType.rawValue)")
}
}
}
refer the link here. You have this workoutActivityType property in HKWorkout objects. The error thrown in valid as you are trying to assign a HKWorkout class object into a Enum definition of HKWorkoutActivityType
self.muscleStrength.append(workouts.workoutActivityType)

How to get heart rate data from HealthKit for each workout

I am attempting to retrieve heart rate for all workouts completed and also start and stop times for the workout and return all values as Times or Quantity items in my JSON result. I have been able to get all workouts by querying for duration greater than 0, but now I would like to get this additional info.
let workoutPredicate = HKQuery.predicateForWorkouts(with: .greaterThanOrEqualTo, duration: 1)
let compound = NSCompoundPredicate(andPredicateWithSubpredicates:
[workoutPredicate])
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate,
ascending: true)
let query = HKSampleQuery(
sampleType: .workoutType(),
predicate: compound,
limit: 0,
sortDescriptors: [sortDescriptor]) { query, samples, error in
DispatchQueue.main.async {
guard let finalSamples = samples as? [HKWorkout] else {
result()
return
}
result(finalSamples.map { sample -> NSDictionary in
return ["duration" : sample.duration, "totalDistance": sample.totalDistance?.doubleValue(for: HKUnit.mile()) as Any, "totalEnergyBurned": sample.totalEnergyBurned?.doubleValue(for: HKUnit.kilocalorie()) as Any]
})
}
}
HKHealthStore().execute(query)
I would like to get the heart rate data for the workout and workout start/end time.
A little late but start & end date/time per workout should be easy with:
print("started #: \(sample.startDate), ended #: \(sample.endDate)")
Did you manage to get heart rates (min/max/avg) per workout? I am also interested to get this & can't seem to figure out if this is possible or not?

Healthkit not returning latest data on iphone. Using healthkit between iPhone and Apple watch

I am creating an app that provides workout information. On apple watch i have three labels that actively shows HEARTRATE ,DISTANCE TRAVELLED and CALORIES BURNED. Things work fine with apple watch, however the area where things go bad is when i try to show this data on iphone in realtime.
APPLE WATCH PART :-
I started workout on apple watch and saved it using folling code
func startWorkoutSession() {
// Start a workout session with the configuration
if let workoutConfiguration = configuration {
do {
workoutSession = try HKWorkoutSession(configuration: workoutConfiguration)
workoutSession?.delegate = self
workoutStartDate = Date()
healthStore.start(workoutSession!)
} catch {
// ...
}
}
}
Then i save that workout on apple watch using following code :-
func saveWorkout() {
// Create and save a workout sample
let configuration = workoutSession!.workoutConfiguration
let isIndoor = (configuration.locationType == .indoor) as NSNumber
print("locationType: \(configuration)")
let workout = HKWorkout(activityType: configuration.activityType,
start: workoutStartDate ?? Date(),
end: workoutEndDate ?? Date(),
workoutEvents: workoutEvents,
totalEnergyBurned: totalEnergyBurned,
totalDistance: totalDistance,
metadata: [HKMetadataKeyIndoorWorkout:isIndoor]);
healthStore.save(workout) { success, _ in
if success {
self.addSamples(toWorkout: workout)
}
}
// Pass the workout to Summary Interface Controller
// WKInterfaceController.reloadRootControllers(withNames: ["StopPauseInterfaceController"], contexts: [workout])
if #available(watchOSApplicationExtension 4.0, *){
// Create the route, save it, and associate it with the provided workout.
routeBuilder?.finishRoute(with: workout, metadata: metadata) { (newRoute, error) in
guard newRoute != nil else {
// Handle the error here...
return
}
}
}
else {
// fallback to earlier versions
}
}
Then i added samples to those workouts using following code :-
func addSamples(toWorkout workout: HKWorkout) {
// Create energy and distance samples
let totalEnergyBurnedSample = HKQuantitySample(type: HKQuantityType.activeEnergyBurned(),
quantity: totalEnergyBurned,
start: workoutStartDate!,
end: workoutEndDate ?? Date())
let totalDistanceSample = HKQuantitySample(type: HKQuantityType.distanceWalkingRunning(),
quantity: totalDistance,
start: workoutStartDate!,
end: workoutEndDate ?? Date())
// Add samples to workout
healthStore.add([totalEnergyBurnedSample, totalDistanceSample], to: workout) { (success: Bool, error: Error?) in
if success {
// Samples have been added
}
}
}
IPHONE PART :-
This is where things get worse. I try to access the healthkit store using HKSampleObjectQuery and It just returns static values. P.S - I am fetching healthkit store every one second for latest data using NSTimer.
The code which is called every second is :-
func extractDataFromHealthStore(identifier : HKQuantityTypeIdentifier,completion: #escaping (String) -> ()) {
let heightType = HKSampleType.quantityType(forIdentifier:identifier)!
let distantPastDate = Date.distantPast
let endDate = Date()
let predicate = HKQuery.predicateForSamples(withStart: distantPastDate, end: endDate, options: .strictStartDate)
// Get the single most recent Value
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
let query = HKSampleQuery(sampleType: heightType, predicate: predicate, limit: 1, sortDescriptors: [sortDescriptor]) { (query, results, error) in
if let result = results?.first as? HKQuantitySample{
print("Height => \(result.quantity)")
completion("\(result.quantity)")
}else{
print("OOPS didnt get height \nResults => \(String(describing: results)), error => \(error)")
completion("")
}
}
self.healthStore.execute(query)
}
Please guide Me if my whole approach is wrong, or if it is right then what is the mistake at my end.

Getting steps from healthkit which was written by other applications

Let's say we have some steps data in healthkit which was auto detected by iphone and written to healthkit. And we have some steps data was enetred by user manually. Now I can differentiate between these steps using this code
let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
print(newDate)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None) // Our search predicate which will fetch all steps taken today
let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: 0, sortDescriptors: nil) { query, results, error in
var steps: Double = 0
//if result.metadata!["HKWasUserEntered"]! == 1{
if results?.count > 0
{
for result in results as! [HKQuantitySample]
{
print("Steps \(result.quantity.doubleValueForUnit(HKUnit.countUnit()))")
print()
// checking and truncating manually added steps
if result.metadata != nil {
}
else{
steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
}
}
print(steps)
}
completion(steps, error)
//}
}
executeQuery(query)
But Lets say if some other app writes some some step's data to healthkit like some fitness app.
Now I am able to read steps with device icon(auto recorded), but
How can I read steps with UP icon as well ?
(UP) is and fitness application by JawBone.

IOS app Performance is too slow for parse data with swiftyjson [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I created app with swift and i used swiftyjson for it. But when i parse images it's a little bit slow how can i improve speed of this. Could you help me about it? I'll share my code in the below thank you.
func parseJSON() {
let path : String = NSBundle.mainBundle().pathForResource("jsonFile", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data: jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
var Name = readableJSON[passedValue,"Product","Ad"]
NumberofRow = readableJSON[passedValue].count
for i in 1...NumberofRow {
var Person = "Product"
Person += "\(i)"
var Name = readableJSON[passedValue][Person]["Ad"].string as String!
var Age = readableJSON[passedValue][Person]["Fiyat"].string as String!
var Image1 = readableJSON[passedValue][Person]["URL"].string as String!
NamesArray.append(Name)
AgeArray.append(Age)
Imagearray.append (Image1)
}
}
You can call function parseJSON in background thread and after it's completion return back to main thread (to update UI accordingly or something else).
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
// Perform data parsing
parseJSON()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// Update UI on main thread
})
})
If you would like to try this approach, I would recommend you to use open-source frameworks for easier work with GCD. For example https://github.com/duemunk/Async. If you use this framework, you can write as simple as following.
Async.background {
// Perform data parsing
parseJSON()
}.main {
// Update UI on main thread
}
Hope it helps you.

Resources