Make Your Fitness App Stand Out with Effort Ratings

How to catch up with Apple's Fitness & Workout App

  • Ben Rudhart
  • 3 min read

Apple raised the bar for fitness apps with the introduction of effort ratings in iOS 18 and watchOS 11! If you missed their announcement, now’s the perfect time to catch up.

With new HealthKit APIs, developers can also bring this highly-requested feature to their own apps. Here’s how you can make your fitness app as polished and user-friendly as Apple’s ✨!

What Are Effort Ratings?

Effort ratings let users log how hard a workout felt, from “Easy” to “All in”. This personal touch can help users track progress, stay motivated, and get more out of every session.

The HealthKit APIs

Apple introduced two key APIs for effort ratings:

As always Apple “forgot” 🙄 to publish the documentation, so here’s what you need to know:

  • The effort rating is an Int value:
    • 0: User skipped the rating
    • 1 to 10: Levels from “Easy” (1) to “All in” (10)
  • Any other value will cause HealthKit to throw an error

Requesting Permissions

Before you can read or write effort ratings, you’ll need user permission:

let effortType = HKQuantityType(.workoutEffortScore)
try await healthStore.requestAuthorization(toShare: [effortType], read: [effortType])

Reading Effort Ratings

To read a stored effort rating for a specific workout:

let predicate = HKQuery.predicateForWorkoutEffortSamplesRelated(workout: workout, activity: nil)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)

let query = HKSampleQuery(
    sampleType: HKQuantityType(.workoutEffortScore),
    predicate: predicate,
    limit: 1,
    sortDescriptors: [sortDescriptor]
) { _, results, error in
    let sample = results?.first as? HKQuantitySample
    let effortRating = sample?.quantity.doubleValue(for: .appleEffortScore())
    // handle effort score
}

healthStore.execute(query)

Writing Effort Ratings

To save a new effort rating for a workout:

let newRating: Int // values 0 ... 10
let sample = HKQuantitySample(
    type: HKQuantityType(.workoutEffortScore),
    quantity: HKQuantity(unit: .appleEffortScore(), doubleValue: Double(newRating)),
    start: workout.startDate,
    end: workout.endDate
)

try await healthStore.relateWorkoutEffortSample(sample, with: workout, activity: nil)

🚀 Introducing WorkoutEffortPicker

Ready to wow your users? Apple’s APIs are powerful, but they didn’t provide a ready-made UI component for effort ratings 😢. That’s where my package WorkoutEffortPicker comes in 🎉🎁!

Why you’ll love it:

  • Built with pure SwiftUI, it closely mimics Apple’s own effort picker
  • Seamless integration — simple to integrate and easy to use
  • Convenience extensions on HKHealthStore make reading and writing effort ratings a breeze
  • The WorkoutEffortScore enum ensures you only use valid effort values, eliminating bugs from invalid entries

Conclusion

Adding effort ratings is a small tweak that can make a huge difference in user engagement and satisfaction. With Apple’s new APIs and the WorkoutEffortPicker package, you can deliver a premium experience that keeps users coming back for more.

Ready to level up your fitness app? 👉 Check out WorkoutEffortPicker on GitHub and improve your app with a few lines of code!

Spotted a typo or have suggestions? Drop a comment or reach out—I’d love to hear your feedback!

Ben Rudhart

Written by: Ben Rudhart

Passionate Freelance Senior Software Engineer. Swift. Kite-Surfing. Piano.