# Apple HealthKit Pedometer UI: Free Step Counter Templates

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-07-01. 6 min read.
> Source: https://vp0.com/blogs/apple-healthkit-pedometer-ui

Two data engines people confuse, one clean UI anatomy. Here is which source powers each screen element, and the permissions that trip everyone up.

**TL;DR.** A step counter UI has two engines people confuse. Apple HealthKit gives aggregated historical totals, right for a daily ring and a weekly chart because it merges iPhone and Apple Watch data. Core Motion's CMPedometer gives live, real-time counting while the app is open, right for a number that ticks up as you walk. The UI is a goal ring, a big step number, distance, and a Swift Charts bar chart, with the goal usually set to the familiar 10,000 steps. Choose the source per screen, add both Info.plist usage keys, and start the UI from a free template rather than drawing rings by hand.

A step counter UI has two possible engines, and picking the wrong one is why so many pedometer apps feel laggy. Apple HealthKit gives you aggregated, historical step totals, the right source for "steps today" and a weekly chart, because it merges data from iPhone and Apple Watch. Core Motion's CMPedometer gives live, real-time counting while the app is open, the right source for a number that ticks up as you walk. The visible design is usually the same handful of parts: a goal ring, a big step number, distance, and a daily bar chart, with the goal almost always set to the familiar [10,000 steps](https://en.wikipedia.org/wiki/Pedometer), a target that actually came from 1960s Japanese pedometer marketing rather than medical research. Choose the data source per screen, get the permissions right, and start the UI from a free template instead of drawing rings by hand.

## HealthKit or Core Motion: which powers your step counter?

They answer different questions, so most real apps use both. [HealthKit](https://developer.apple.com/documentation/healthkit) is the historical store: you read the stepCount quantity type and run an [HKStatisticsCollectionQuery](https://developer.apple.com/documentation/healthkit/hkstatisticscollectionquery) to get one total per day, which is exactly what a weekly chart or a "today so far" ring needs. It also deduplicates iPhone and Apple Watch steps for you, which hand-rolled counting cannot.

Core Motion is the live wire. [CMPedometer](https://developer.apple.com/documentation/coremotion/cmpedometer) can query a past range, but its real value is startUpdates, which streams step, distance, pace, and floor counts in real time while your app is foregrounded. If you want the number to climb as the user walks on your screen, that is CMPedometer, not HealthKit. The clean split is history from HealthKit, live motion from Core Motion, which is the same architecture behind [an Apple HealthKit step counter template](/blogs/apple-healthkit-step-counter-swiftui-template/).

## What does the step-counter UI actually need?

Four or five elements, each backed by a specific source. The anatomy is consistent across pedometer apps, so a template gets you most of the way and you bind the data underneath.

| Screen element | Data source | Note |
| --- | --- | --- |
| Progress ring toward goal | HealthKit steps today | goal defaults to 10,000, make it editable |
| Big live step number | CMPedometer startUpdates | ticks up in real time while foregrounded |
| Distance and pace | CMPedometer | already computed, no extra math |
| Weekly bar chart | HealthKit daily buckets | one HKStatisticsCollectionQuery fills it |
| Streak or badge | your own store of daily totals | motivational, not from the sensor |

The chart is where Swift Charts earns its place: a week of daily totals from HealthKit maps directly to a bar mark, no custom drawing. The ring and badge patterns are shared with other HealthKit surfaces like [a fasting timer ring](/blogs/apple-healthkit-intermittent-fasting-timer-ring/), and the overall layout matches [a fitness tracker UI kit](/blogs/fitness-tracker-ui-kit/).

## How do you get the permissions right?

Two different permission systems, and forgetting either crashes the app. HealthKit needs an explicit authorization request through HKHealthStore for the stepCount read type, plus an NSHealthShareUsageDescription string in Info.plist explaining why. Core Motion needs its own NSMotionUsageDescription key. Ship without those Info.plist strings and iOS terminates the app the instant you touch the API, which is a common first-run crash.

Design for denial, because health permission is often refused. When HealthKit access is not granted, the ring and chart have no data, so show an honest empty state with a one-tap path to Settings rather than a blank screen or fake zeros. Requesting only the read types you use, and asking at the moment the value is needed rather than on launch, both raise the acceptance rate.

## Common mistakes building a pedometer UI

The performance mistake is driving a live, ticking counter from HealthKit. HealthKit is a database, not a stream, so polling it for a number that should climb every step feels sluggish; use CMPedometer startUpdates for the live figure and reserve HealthKit for totals and history. The related bug is double counting: reading raw samples instead of HealthKit's statistics can add iPhone and Apple Watch steps together, so use the statistics query, which reconciles sources.

The rest are lifecycle details. CMPedometer live updates only run while the app is foregrounded, so a counter that "stops" in the background is working as designed; backfill from HealthKit when the app returns. And assuming permission was granted, rather than checking the authorization status, leaves the UI stuck, the same handling that a [React Native step counter widget](/blogs/react-native-step-counter-widget-ios/) has to get right for the home screen.

## Key takeaways: an Apple HealthKit pedometer UI

- Use HealthKit for historical and daily totals, and Core Motion's CMPedometer for the live, real-time step number.
- Build the standard anatomy: a goal ring, a big step count, distance, and a weekly Swift Charts bar chart, with an editable 10,000-step default.
- Read steps with HKStatisticsCollectionQuery so iPhone and Apple Watch data is deduplicated instead of double counted.
- Add both Info.plist keys, NSHealthShareUsageDescription and NSMotionUsageDescription, or the app crashes on first access.
- Design an honest empty state for denied permission, and remember CMPedometer live updates pause in the background.

## Frequently asked questions

**How do I build a step counter UI with Apple HealthKit?**
Read the stepCount quantity type with an HKStatisticsCollectionQuery to get one total per day, drive a goal ring and a weekly Swift Charts bar chart from those totals, and request HealthKit authorization with an NSHealthShareUsageDescription in Info.plist. For a number that ticks up live as the user walks, add Core Motion's CMPedometer startUpdates. Starting from a free template gives you the ring and chart so you only bind the data.

**Should I use HealthKit or Core Motion for step counting?**
Use both for different jobs. HealthKit provides accurate historical and daily totals and merges iPhone and Apple Watch data, which suits rings, charts, and streaks. Core Motion's CMPedometer streams live steps, distance, and pace while the app is open, which suits a real-time counter. Driving a live ticking number from HealthKit feels laggy, so reserve it for history.

**Why does my pedometer app crash when it reads steps?**
Almost always a missing Info.plist usage string. HealthKit requires NSHealthShareUsageDescription and Core Motion requires NSMotionUsageDescription, and iOS terminates the app immediately if it touches those APIs without the matching key. Add both descriptions, then request authorization before reading any data.

**Is 10,000 steps a scientifically required goal?**
No. The 10,000-step target originated as a 1960s Japanese marketing name for a pedometer, not a medical guideline, and later research found health benefits accrue well below it. Treat 10,000 as a familiar default in the UI but make the goal editable, since users have different targets.

**Does the live step counter keep running in the background?**
No. CMPedometer's live updates run only while your app is in the foreground, so a counter that appears to stop when the user leaves is behaving correctly. When the app returns, query HealthKit for the day's total to backfill any steps taken while you were not streaming, so the number stays accurate.

## Frequently asked questions

### How do I build a step counter UI with Apple HealthKit?

Read the stepCount quantity type with an HKStatisticsCollectionQuery to get one total per day, drive a goal ring and a weekly Swift Charts bar chart from those totals, and request HealthKit authorization with an NSHealthShareUsageDescription in Info.plist. For a number that ticks up live as the user walks, add Core Motion's CMPedometer startUpdates. Starting from a free template gives you the ring and chart so you only bind the data.

### Should I use HealthKit or Core Motion for step counting?

Use both for different jobs. HealthKit provides accurate historical and daily totals and merges iPhone and Apple Watch data, which suits rings, charts, and streaks. Core Motion's CMPedometer streams live steps, distance, and pace while the app is open, which suits a real-time counter. Driving a live ticking number from HealthKit feels laggy, so reserve it for history.

### Why does my pedometer app crash when it reads steps?

Almost always a missing Info.plist usage string. HealthKit requires NSHealthShareUsageDescription and Core Motion requires NSMotionUsageDescription, and iOS terminates the app immediately if it touches those APIs without the matching key. Add both descriptions, then request authorization before reading any data.

### Is 10,000 steps a scientifically required goal?

No. The 10,000-step target originated as a 1960s Japanese marketing name for a pedometer, not a medical guideline, and later research found health benefits accrue well below it. Treat 10,000 as a familiar default in the UI but make the goal editable, since users have different targets.

### Does the live step counter keep running in the background?

No. CMPedometer's live updates run only while your app is in the foreground, so a counter that appears to stop when the user leaves is behaving correctly. When the app returns, query HealthKit for the day's total to backfill any steps taken while you were not streaming, so the number stays accurate.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
