Swift CMMotionActivityManager не отображает правильный статус авторизации

Я пытаюсь создать очень простой счетчик шагов и следую статье Камиля Высоцкого по адресу https://brightinventions.pl/blog/coremotion-pedometer-swift/. Однако мой .isActivityAvailable() возвращает False, предотвращая запуск любой из моих других функций. Кроме того, мой вызов CMMotionActivityManager.authorizationStatus() возвращает 3 (отклонено). Я не могу в жизни понять, почему это происходит.

Я добавил Motion Usage Description в свой info.plist с описанием и включил авторизацию на своем симуляторе iPhone. Я также пытался имитировать режим «Прогулка по городу» в меню отладки, что не помогает. Мой код ниже.

import UIKit
import CoreMotion
import CoreLocation

class ViewController: UIViewController {

    @IBOutlet weak var startButton: UIButton!
    @IBOutlet weak var activityTypeLabel: UILabel!
    @IBOutlet weak var stepsCountLabel: UILabel!

    private let activityManager = CMMotionActivityManager()
    private let pedometer = CMPedometer()
    private var shouldStartUpdating: Bool = false
    private var startDate: Date? = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        startButton.addTarget(self, action: #selector(didTapStartButton), for: .touchUpInside)

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        guard let startDate = startDate else { return }
        updateStepsCountLabelUsing(startDate: startDate)
    }

    @objc private func didTapStartButton() {
        shouldStartUpdating = !shouldStartUpdating
        shouldStartUpdating ? (onStart()) : (onStop())
    }
}


extension ViewController {
    private func onStart() {
        startButton.setTitle("Stop", for: .normal)
        startDate = Date()
        checkAuthorizationStatus()
        startUpdating()
    }

    private func onStop() {
        startButton.setTitle("Start", for: .normal)
        startDate = nil
        stopUpdating()
    }

    private func startUpdating() {
        if CMMotionActivityManager.isActivityAvailable() {
            startTrackingActivityType()
        } else {
            activityTypeLabel.text = "Not available"
        }

        if CMPedometer.isStepCountingAvailable() {
            startCountingSteps()
        } else {
            stepsCountLabel.text = "Not available"
        }
    }

    private func checkAuthorizationStatus() {
        switch CMMotionActivityManager.authorizationStatus() {
        case CMAuthorizationStatus.denied:
            onStop()
            activityTypeLabel.text = "Not available"
            stepsCountLabel.text = "Not available"
        default:break
        }
    }

    private func stopUpdating() {
        activityManager.stopActivityUpdates()
        pedometer.stopUpdates()
        pedometer.stopEventUpdates()
    }

    private func on(error: Error) {
        //handle error
    }

    private func updateStepsCountLabelUsing(startDate: Date) {
        pedometer.queryPedometerData(from: startDate, to: Date()) {
            [weak self] pedometerData, error in
            if let error = error {
                self?.on(error: error)
            } else if let pedometerData = pedometerData {
                DispatchQueue.main.async {
                    self?.stepsCountLabel.text = String(describing: pedometerData.numberOfSteps)
                }
            }
        }
    }

    private func startTrackingActivityType() {
        activityManager.startActivityUpdates(to: OperationQueue.main) {
            [weak self] (activity: CMMotionActivity?) in
            guard let activity = activity else { return }
            DispatchQueue.main.async {
                if activity.walking {
                    self?.activityTypeLabel.text = "Walking"
                } else if activity.stationary {
                    self?.activityTypeLabel.text = "Stationary"
                } else if activity.running {
                    self?.activityTypeLabel.text = "Running"
                } else if activity.automotive {
                    self?.activityTypeLabel.text = "Automotive"
                }
            }
        }
    }

    private func startCountingSteps() {
        pedometer.startUpdates(from: Date()) {
            [weak self] pedometerData, error in
            guard let pedometerData = pedometerData, error == nil else { return }

            DispatchQueue.main.async {
                self?.stepsCountLabel.text = pedometerData.numberOfSteps.stringValue
            }
        }
    }
}

Вот мой viewController после запуска и нажатия кнопки "Пуск"

Заранее большое спасибо всем, кто может предложить какие-либо знания!!!


person MadMacciato    schedule 22.07.2018    source источник
comment
Пожалуйста, попробуйте запустить свой код на устройстве iOS, так как ядро ​​​​движения использует датчики устройства для получения информации о действиях пользователя.   -  person Hemant Solanki    schedule 19.09.2018


Ответы (1)


Используйте этот код для проверки статуса авторизации:

 let manager = CMMotionActivityManager()


 let today = Date()

    manager.queryActivityStarting(from: today, to: today, to: OperationQueue.main, withHandler: { (activities: [CMMotionActivity]?, error: Error?) -> () in
        if error != nil {
            let errorCode = (error! as NSError).code
            if errorCode == Int(CMErrorMotionActivityNotAuthorized.rawValue) {
                print("NotAuthorized")
            }
        } else {
            print("Authorized")
         //Start Tracking Activity 
        }
        manager.stopActivityUpdates()
    })

Надеюсь, это сработает для вас.

person Hemant Solanki    schedule 19.09.2018