iOS Swift Development : Step Counter app using Pedometer data

April 11, 2015
Shrikar Archak

<Image alt="Step Counter app using Pedometer data" objectFit="contain" src="/static/images/sc21.png" height={300} width={1000} placeholder="blur" quality={100} />

We will be building a simple step counter app which uses a pedometer data to retrieve step counts and other information about the distance traveled and the number of floors ascended or descended. The pedometer object manages a cache of historic data that you can query or you can ask for live updates as the data is processed.

The CMMotionActivity class contains the data for a single motion update event. On devices that support motion, you can use a CMMotionActivityManager object to request updates when the current type of motion changes. When a change occurs, the update information is packaged into a CMMotionActivity object and sent to your app.

CMMotionActivity contains state related to many of the activites like stationary, walking, running, automative, cycling and unknown. Also along with that it provides confidence about how accurate the motion data is.

CMPedoMeter and CMMotionActivityManager will work on actual devices.

In the mainstory board let go ahead and start adding the UILabel’s and UIImageview.

  • Add Labels for the Today,Steps,Activity state.
  • Add imageview for the shoe and the state (Either running, walking, stationary,automotive)
  • Setup the IBOutlet for all the above.
  • More on autolayouts AutoLayout Part 1 and Autolayout part 2

<Image alt="Step Counter app using Pedometer data" objectFit="contain" src="/static/images/sc1.png" height={300} width={1000} placeholder="blur" quality={100} />

<Image alt="Step Counter app using Pedometer data" objectFit="contain" src="/static/images/sc2.png" height={300} width={1000} placeholder="blur" quality={100} />

There are multiple ways we can query the data from the CMPedometer and the CMActivityManager.

  • Realtime push as the events happen
  • Query cached data with start and end date.

In this app I am currently using both of the above methods. When the app starts up I fetch the data from midnight till now to get the steps for today and update the View. self.pedoMeter.queryPedometerDataFromDate(midnightOfToday, toDate: NSDate())

Along with we utilize the realtime push from the framework to show the latest steps and the current activity.

self.pedoMeter.startPedometerUpdatesFromDate(midnightOfToday)

//
//  ViewController.swift
//  Steps
//
//  Created by Shrikar Archak on 4/11/15.
//  Copyright (c) 2015 Shrikar Archak. All rights reserved.
//

import UIKit
import CoreMotion
class ViewController: UIViewController {

    @IBOutlet weak var activityState: UILabel!
    @IBOutlet weak var steps: UILabel!

    var days:\[String\] = \[\]
    var stepsTaken:\[Int\] = \[\]

    @IBOutlet weak var stateImageView: UIImageView!
    let activityManager = CMMotionActivityManager()
    let pedoMeter = CMPedometer()

    override func viewDidLoad() {

        super.viewDidLoad()

        let cal = NSCalendar.currentCalendar()
        var comps = cal.components(NSCalendarUnit.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit, fromDate: NSDate())
        comps.hour = 0
        comps.minute = 0
        comps.second = 0
        let timeZone = NSTimeZone.systemTimeZone()
        cal.timeZone = timeZone

        let midnightOfToday = cal.dateFromComponents(comps)!


        if(CMMotionActivityManager.isActivityAvailable()){
            self.activityManager.startActivityUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (data: CMMotionActivity!) -> Void in
               dispatch\_async(dispatch\_get\_main\_queue(), { () -> Void in
                if(data.stationary == true){
                    self.activityState.text = "Stationary"
                    self.stateImageView.image = UIImage(named: "Sitting")
                } else if (data.walking == true){
                    self.activityState.text = "Walking"
                    self.stateImageView.image = UIImage(named: "Walking")
                } else if (data.running == true){
                    self.activityState.text = "Running"
                    self.stateImageView.image = UIImage(named: "Running")
                } else if (data.automotive == true){
                    self.activityState.text = "Automotive"
                }
               })

           })
        }
        if(CMPedometer.isStepCountingAvailable()){
            let fromDate = NSDate(timeIntervalSinceNow: -86400 \* 7)
            self.pedoMeter.queryPedometerDataFromDate(fromDate, toDate: NSDate()) { (data : CMPedometerData!, error) -> Void in
                println(data)
                dispatch\_async(dispatch\_get\_main\_queue(), { () -> Void in
                    if(error == nil){
                        self.steps.text = "\\(data.numberOfSteps)"
                    }
                })

            }

            self.pedoMeter.startPedometerUpdatesFromDate(midnightOfToday) { (data: CMPedometerData!, error) -> Void in
                dispatch\_async(dispatch\_get\_main\_queue(), { () -> Void in
                    if(error == nil){
                        self.steps.text = "\\(data.numberOfSteps)"
                    }
                })
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }

}

Subscribe to the newsletter

Get notified when new content or topic is released.

You won't receive any spam! ✌️