CoreMotion
Access accelerometer, gyroscope, attitude/device motion, pedometer, altitude, and specialized sensors using Core Motion. Targets Swift 6.3 / iOS 26+.
Contents
- Setup & Authorization
- Motion Manager & Raw Sensors
- Device Motion (Attitude & Gravity)
- Pedometer & Activity Recognition
- Altimeter & Specialized Sensors
- Battery & Lifecycle
- Common Mistakes
- Review Checklist
- References
Setup & Authorization
Add NSMotionUsageDescription to Info.plist explaining why the app accesses motion sensors.
Check authorization status for managers exposing privacy controls (CMPedometer, CMMotionActivityManager, CMAltimeter):
import CoreMotion
guard CMMotionActivityManager.authorizationStatus() != .denied else {
// Prompt user to enable motion permissions in Settings
return
}
Raw accelerometer/gyro streams under CMMotionManager do not prompt for permission directly but require the usage description and throw errors on unauthorized access.
Motion Manager & Raw Sensors
Maintain exactly one shared CMMotionManager instance per application to avoid sensor contention:
final class MotionProvider {
static let shared = MotionProvider()
let manager = CMMotionManager()
func startAccelerometer() {
guard manager.isAccelerometerAvailable else { return }
manager.accelerometerUpdateInterval = 1.0 / 60.0 // 60 Hz
manager.startAccelerometerUpdates(to: .main) { data, error in
guard let accel = data?.acceleration else { return }
// Process acceleration: x, y, z
}
}
func stop() {
manager.stopAccelerometerUpdates()
}
}
Device Motion (Attitude & Gravity)
Prefer CMDeviceMotion over raw sensor data. It fuses accelerometer, gyro, and magnetometer data into clean attitude, user acceleration, and gravity vectors:
manager.deviceMotionUpdateInterval = 1.0 / 60.0
manager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: .main) { motion, error in
guard let motion else { return }
let roll = motion.attitude.roll
let pitch = motion.attitude.pitch
let yaw = motion.attitude.yaw
}
Pedometer & Activity Recognition
Track steps, distance, and user movement state:
let pedometer = CMPedometer()
if CMPedometer.isStepCountingAvailable() {
pedometer.startUpdates(from: .now) { data, error in
guard let data else { return }
print("Steps: \(data.numberOfSteps)")
}
}
let activityManager = CMMotionActivityManager()
if CMMotionActivityManager.isActivityAvailable() {
activityManager.startActivityUpdates(to: .main) { activity in
guard let activity else { return }
if activity.walking { print("Walking") }
if activity.running { print("Running") }
}
}
Altimeter & Specialized Sensors
- CMAltimeter: Track relative altitude changes or absolute barometric pressure (
startRelativeAltitudeUpdates). - CMHeadphoneMotionManager: Track head pose from AirPods for spatial audio interactions.
- CMBatchedSensorManager (iOS 17+): Receive batched high-frequency workout motion data with low CPU wake overhead.
- CMWaterSubmersionManager: Track depth, temperature, and submersion state on supported Apple Watch hardware.
Battery & Lifecycle
- Stop updates (
stopDeviceMotionUpdates()) when views disappear or when the app transitions to the background. - Select the lowest sensor update frequency adequate for your feature (e.g. 10–20 Hz for tilt detection; 60 Hz only for real-time physics/gaming).
Common Mistakes
- Instantiating multiple CMMotionManager objects: Degrades system update rates and increases battery drain. Use a single shared manager.
- Missing NSMotionUsageDescription: The app crashes immediately upon accessing activity, pedometer, or altimeter services.
- Not stopping updates on backgrounding: Running motion updates indefinitely drains battery and causes system termination.
- Using raw accelerometer for orientation: Raw data includes gravity and user movement noise. Use
CMDeviceMotion.attitudeinstead. - Omitting availability checks: Always check
isAvailableflags before callingstartUpdates.
Review Checklist
-
NSMotionUsageDescriptionpresent and descriptive in Info.plist - Single shared
CMMotionManagerinstance used app-wide - Sensor availability checked before initiating streams
- Updates explicitly halted when views dismiss or background transitions occur
-
CMDeviceMotionused for orientation and tilt calculations instead of raw accelerometer - Update intervals chosen conservatively to preserve battery life
References
- Extended patterns (SwiftUI integration, batched sensor manager, headphone motion, water submersion): references/motion-patterns.md
- CoreMotion framework
- CMMotionManager
- CMPedometer
- CMMotionActivityManager
- CMDeviceMotion
- CMAltimeter
- CMAbsoluteAltitudeData
- CMBatchedSensorManager
- CMHeadphoneMotionManager
- CMWaterSubmersionManager
- Accessing submersion data
- Getting processed device-motion data