Skip to content
AF
Phone Sensors

CMAltimeter: relative and absolute altitude on iPhone and Apple Watch

Last verified October 3, 2026 · 4 min read

CMAltimeter is Core Motion's class for altitude changes, and it reports two different things. Relative altitude, from iOS 8.0 and watchOS 2.0, is the change in meters since the first event your app received, alongside barometric pressure in kilopascals. Absolute altitude, from iOS 15.0 and watchOS 8.0, is the device's height relative to sea level with an accuracy estimate, and Apple states it is only available on iPhone 12 and later and Apple Watch 6 or SE and later. Both need NSMotionUsageDescription in Info.plist, and Apple tells you to check isRelativeAltitudeAvailable() or isAbsoluteAltitudeAvailable() before starting either stream.

Hiking, stair workouts and trail runs all want elevation, and the phone has a barometer for it. Apple's CMAltimeter documentation, read 2026-10-03, splits the job into two streams that answer different questions.

Two streams, two questions#

Relative altitudeAbsolute altitude
Start callstartRelativeAltitudeUpdates(to:withHandler:)startAbsoluteAltitudeUpdates(to:withHandler:)
Data classCMAltitudeDataCMAbsoluteAltitudeData
What you getrelativeAltitude in meters since the first event; pressure in kilopascalsaltitude in meters relative to sea level; accuracy and precision in meters
Availability checkisRelativeAltitudeAvailable()isAbsoluteAltitudeAvailable()
Since (iOS / watchOS)8.0 / 2.015.0 / 8.0

Apple's own example covers both: a hiking app "could use this object to track the user's elevation change over the course of a hike, or to report their current absolute altitude during the hike."

Relative altitude is relative to your first event#

Apple: "For the first altitude event delivered to your altimeter object, the value of this property is 0. Subsequent events contain a number that reflects the relative change in altitude with respect to the first reported event." Each time you start the stream, zero moves to wherever the user is standing. If a session can stop and restart, store the last value before stopping and add it back, or the climb resets mid-hike.

Calling the start method again replaces the handler: "Only the last installed handler receives events." And on a device without the hardware it fails silently: "If altitude data isn't available on the current device, this method does nothing." Hence the availability check.

Absolute altitude: which devices#

Apple repeats one sentence on the availability check, the start method and the data class: "Absolute altitude is only available on iPhone 12 and later and Apple Watch 6 or SE and later." CMAbsoluteAltitudeData adds accuracy ("The estimated uncertainty of the altimeter in meters, based on one standard deviation") and precision ("The recommended resolution for the altitude, in meters"). Use precision to decide how many digits to display; showing centimetres when Apple recommends a coarser resolution is false precision. Apple notes the altitude "can be positive or negative."

Events arrive on a schedule, not on change#

"Core Motion generates events at regular intervals (regardless of whether the data has changed)". Apple does not state the interval. Expect a steady stream of nearly identical values while the user stands still, and do not treat each event as movement.

import CoreMotion

let altimeter = CMAltimeter()
var climbed = 0.0
var last: Double?

func startClimbTracking() {
    guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
    altimeter.startRelativeAltitudeUpdates(to: .main) { data, error in
        guard let metres = data?.relativeAltitude.doubleValue, error == nil else { return }
        if let previous = last, metres - previous > 0 {
            climbed += metres - previous           // gain only; tune a threshold on real data
        }
        last = metres
    }
}

func stopClimbTracking() { altimeter.stopRelativeAltitudeUpdates() }

The gain arithmetic is ours, not Apple's. Summing every small upward wiggle from a barometer will overstate a climb; most apps add a minimum step before counting. Apple publishes no noise figure for relative altitude, so the threshold is something to tune against recorded sessions.

Permission#

The class page carries the usual Core Motion warning: include NSMotionUsageDescription, because "If you don't include a usage description string, your app crashes when you call this API." authorizationStatus() arrived in iOS 11.0 and watchOS 4.0. Apple's CMAltimeter page lists no macOS version.

Pitfalls#

  • Expecting zero to mean sea level. In the relative stream it means the point where this stream started.
  • Restarting mid-session. The baseline resets. Carry the previous total across.
  • Skipping the availability check. The start method does nothing on unsupported hardware, with no error.
  • Promising absolute altitude on older phones. Apple names iPhone 12 and Apple Watch 6 or SE as the floor.
  • Counting every event as movement. Events are periodic whether or not anything changed.
  • Looking for history. The CMAltimeter page lists start and stop methods only, with no query for past altitude.

For stair counting without your own arithmetic, CMPedometer reports floorsAscended, which Apple sizes at approximately three meters per floor and limits to walking or running up stairs. Why hiking apps disagree on elevation gain is covered in building a hiking app.

Frequently asked questions

Which iPhones support CMAltimeter absolute altitude?
Apple's documentation says absolute altitude is only available on iPhone 12 and later and Apple Watch 6 or SE and later. The API itself needs iOS 15.0 or watchOS 8.0. Call isAbsoluteAltitudeAvailable() before startAbsoluteAltitudeUpdates(to:withHandler:) rather than checking model names yourself, and fall back to relative altitude, which has been available since iOS 8.0 on devices that support it.
Why does CMAltimeter relativeAltitude start at zero?
Because it measures change since your stream began. Apple says the first altitude event delivered to your altimeter object has a relativeAltitude of 0, and later events reflect the change with respect to that first event. Every call to startRelativeAltitudeUpdates(to:withHandler:) sets a new zero. If a hike can pause and resume, keep the last value before stopping and add it to the new stream's readings.
What unit is CMAltitudeData pressure reported in?
Kilopascals. Apple documents the pressure property of CMAltitudeData as the recorded pressure, in kilopascals, delivered alongside relativeAltitude in meters. Weather services often quote hectopascals or millibars, which are ten times larger numbers for the same pressure, so convert before comparing a phone reading with a forecast.
Should I use CMAltimeter or CMPedometer floorsAscended to count stairs?
For a simple floors figure, CMPedometer is less work. Apple documents floorsAscended as counting only floors climbed while walking or running up stairs, excluding elevators, with a floor of approximately three meters. CMAltimeter gives you continuous relative altitude in meters, which suits a stair workout that needs height per minute or a hike's elevation profile, but turning it into gain is your own arithmetic. Check isFloorCountingAvailable() or isRelativeAltitudeAvailable() first.

All 40 questions in Phone Sensors →

Keep reading

Next steps

Was this page useful?

Independent comparison, last reviewed October 3, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.

← All phone sensors · by AIFitnessAPI