Skip to content
Mobile
Skill

/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

From plugin
swift-ios-skills
1.3k86 skills1 MCP

Claude Code

$ npx -y skills add dpearson2699/swift-ios-skills --skill core-motion --agent claude-code

SKILL.md

core-motion.SKILL.md
name: core-motion
description: "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."

CoreMotion

Read device motion, pedometer/activity, altitude, headphone, batched-workout, and submersion sensors with Core Motion. Scope: 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.

<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.

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.

import CoreMotion

let motionManager = CMMotionManager()

Accelerometer Updates

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

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:

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.

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:

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.

let pedometer = CMPedometer()

guard CMPedometer.isStepCountingAvailable() else { return }

// Historical query
pedometer.queryPedometerData(
    fr
Read more
@dpearson2699
Ships withswift-ios-skills

86 agent skills optimized for iOS 26+ development with Swift 6.3 and modern Apple frameworks.

1.3k86 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of dpearson2699/swift-ios-skills on GitHub, a chart by star-history.com

Other skills on swift-ios-skills.

alarmkit

alarmkit

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple…

app-clips

app-clips

Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo1d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about core-motion.

Which coding agents can use core-motion?
core-motion installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.