core-motion
Access Core Motion accelerometer, gyroscope, magnetometer, device-motion, pedometer, activity-recognition, altitude, headphone motion, batched high-frequency workout motion, and water-submersion/depth data. Use when reading device sensors, counting steps, detecting walking/running/driving/cycling, tracking altitude, building motion interactions, handling AirPods head tracking, or implementing watchOS dive/depth features.
What this skill does
# CoreMotion
Read device sensor data -- accelerometer, gyroscope, magnetometer, pedometer,
activity recognition, altitude, headphone motion, batched motion, and submersion
depth -- on iOS and watchOS. CoreMotion fuses raw sensor inputs into processed
device-motion data and provides pedometer/activity APIs for fitness and
navigation use cases. Targets Swift 6.3 / iOS 26+.
## Contents
- [Setup](#setup)
- [CMMotionManager: Sensor Data](#cmmotionmanager-sensor-data)
- [Processed Device Motion](#processed-device-motion)
- [CMPedometer: Step and Distance Data](#cmpedometer-step-and-distance-data)
- [CMMotionActivityManager: Activity Recognition](#cmmotionactivitymanager-activity-recognition)
- [CMAltimeter: Altitude Data](#cmaltimeter-altitude-data)
- [Update Intervals and Battery](#update-intervals-and-battery)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## Setup
### Info.plist
Add `NSMotionUsageDescription` to Info.plist with a user-facing string explaining
why your app needs motion data. Without this key, the app crashes on first access.
```xml
<key>NSMotionUsageDescription</key>
<string>This app uses motion data to track your activity.</string>
```
### Authorization
Use the matching manager's `authorizationStatus()` or `authorizationStatus`
property when an API exposes one (`CMPedometer`, `CMMotionActivityManager`,
`CMAltimeter`, headphone motion, batched sensors, and submersion). Raw
`CMMotionManager` accelerometer/gyro/device-motion streams have no explicit
authorization request API; still ship the usage string and handle errors from
start/update callbacks.
```swift
import CoreMotion
let status = CMMotionActivityManager.authorizationStatus()
switch status {
case .notDetermined:
// Will prompt on first use
break
case .authorized:
break
case .restricted, .denied:
// Direct user to Settings
break
@unknown default:
break
}
```
## CMMotionManager: Sensor Data
Create exactly **one** `CMMotionManager` per app. Multiple instances degrade
sensor update rates.
```swift
import CoreMotion
let motionManager = CMMotionManager()
```
### Accelerometer Updates
```swift
guard motionManager.isAccelerometerAvailable else { return }
motionManager.accelerometerUpdateInterval = 1.0 / 60.0 // 60 Hz
motionManager.startAccelerometerUpdates(to: .main) { data, error in
guard let acceleration = data?.acceleration else { return }
print("x: \(acceleration.x), y: \(acceleration.y), z: \(acceleration.z)")
}
// When done:
motionManager.stopAccelerometerUpdates()
```
### Gyroscope Updates
```swift
guard motionManager.isGyroAvailable else { return }
motionManager.gyroUpdateInterval = 1.0 / 60.0
motionManager.startGyroUpdates(to: .main) { data, error in
guard let rotationRate = data?.rotationRate else { return }
print("x: \(rotationRate.x), y: \(rotationRate.y), z: \(rotationRate.z)")
}
motionManager.stopGyroUpdates()
```
### Polling Pattern (Games)
For games, start updates without a handler and poll the latest sample each frame:
```swift
motionManager.startAccelerometerUpdates()
// In your game loop / display link:
if let data = motionManager.accelerometerData {
let tilt = data.acceleration.x
// Move player based on tilt
}
```
## Processed Device Motion
Device motion fuses accelerometer, gyroscope, and magnetometer into a single
`CMDeviceMotion` object with attitude, user acceleration (gravity removed),
rotation rate, and calibrated magnetic field.
When giving device-motion guidance, show the runtime frame check in the snippet
instead of hard-coding a corrected, magnetic-north, or true-north frame. Fall
back to `.xArbitraryZVertical` when the preferred frame is unavailable.
```swift
guard motionManager.isDeviceMotionAvailable else { return }
let availableFrames = CMMotionManager.availableAttitudeReferenceFrames()
let frame: CMAttitudeReferenceFrame = availableFrames.contains(.xArbitraryCorrectedZVertical)
? .xArbitraryCorrectedZVertical
: .xArbitraryZVertical
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
motionManager.startDeviceMotionUpdates(
using: frame,
to: .main
) { motion, error in
guard let motion else { return }
let attitude = motion.attitude // roll, pitch, yaw
let userAccel = motion.userAcceleration
let gravity = motion.gravity
let heading = motion.heading // degrees relative to the current frame
print("Pitch: \(attitude.pitch), Roll: \(attitude.roll)")
}
motionManager.stopDeviceMotionUpdates()
```
### Attitude Reference Frames
For simple tilt controls, use `.xArbitraryZVertical` or
`.xArbitraryCorrectedZVertical`; they avoid magnetometer/location dependencies.
Before requesting corrected, magnetic-north, or true-north frames, call
`CMMotionManager.availableAttitudeReferenceFrames()` and fall back to an
available frame.
| Frame | Use Case |
|---|---|
| `.xArbitraryZVertical` | Default. Z is vertical, X arbitrary at start. Most games. |
| `.xArbitraryCorrectedZVertical` | Same as above, corrected for gyro drift over time. |
| `.xMagneticNorthZVertical` | X points to magnetic north. Requires magnetometer. |
| `.xTrueNorthZVertical` | X points to true north. Requires magnetometer + location. |
Check available frames before use:
```swift
let available = CMMotionManager.availableAttitudeReferenceFrames()
if available.contains(.xTrueNorthZVertical) {
// Safe to use true north
}
```
## CMPedometer: Step and Distance Data
`CMPedometer` provides step counts, distance, pace, cadence, and floor counts.
```swift
let pedometer = CMPedometer()
guard CMPedometer.isStepCountingAvailable() else { return }
// Historical query
pedometer.queryPedometerData(
from: Calendar.current.startOfDay(for: Date()),
to: Date()
) { data, error in
guard let data else { return }
print("Steps today: \(data.numberOfSteps)")
print("Distance: \(data.distance?.doubleValue ?? 0) meters")
print("Floors up: \(data.floorsAscended?.intValue ?? 0)")
}
// Live updates
pedometer.startUpdates(from: Date()) { data, error in
guard let data else { return }
print("Steps: \(data.numberOfSteps)")
}
// Stop when done
pedometer.stopUpdates()
```
### Availability Checks
| Method | What It Checks |
|---|---|
| `isStepCountingAvailable()` | Step counter hardware |
| `isDistanceAvailable()` | Distance estimation |
| `isFloorCountingAvailable()` | Barometric altimeter for floors |
| `isPaceAvailable()` | Pace data |
| `isCadenceAvailable()` | Cadence data |
## CMMotionActivityManager: Activity Recognition
Detects whether the user is stationary, walking, running, cycling, or in a vehicle.
```swift
let activityManager = CMMotionActivityManager()
guard CMMotionActivityManager.isActivityAvailable() else { return }
// Live activity updates
activityManager.startActivityUpdates(to: .main) { activity in
guard let activity else { return }
if activity.walking {
print("Walking (confidence: \(activity.confidence.rawValue))")
} else if activity.running {
print("Running")
} else if activity.automotive {
print("In vehicle")
} else if activity.cycling {
print("Cycling")
} else if activity.stationary {
print("Stationary")
}
}
activityManager.stopActivityUpdates()
```
### Historical Activity Query
```swift
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
activityManager.queryActivityStarting(
from: yesterday,
to: Date(),
to: .main
) { activities, error in
guard let activities else { return }
for activity in activities {
print("\(activity.startDate): walking=\(activity.walking)")
}
}
```
## CMAltimeter: Altitude Data
Altimeter access is covered by `NSMotionUsageDescription`; handle denied motion
access through unavailable data and update-handler errors.
```swift
let altimeter = CMAltimeter()
guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
Related in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.