My app uses the barometric data from the CMAltimeter on iOS (iPhone). That has always worked just fine. But after installing iOS 17.4, it stopped working. Other apps that use barometric data also stopped working. So it appears to be a major fault in iOS 17.4.
Below is the (Swift) code used to test this. This code used to work fine with earlier versions of iOS, but in 17.4, the authorizationStatus()
returns .restricted
, and the handler is called with the error:
The operation couldn’t be completed. (CMErrorDomain error 105.)
This all indicates there is some authentication failure. I have logged bug report with Apple.
But I wonder if others experienced the same, and if there is some work-around/solution that makes barometric data available again.
if CMAltimeter.isRelativeAltitudeAvailable() {
status = CMAltimeter.authorizationStatus()
self.altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) { (data, _error) in
DispatchQueue.main.async {
error = _error != nil ? _error!.localizedDescription : "<nil>"
print(error)
pressure = data != nil ? String(format: "%f", data!.pressure.doubleValue) : ""
}
}
}
PS: the documentation of Core Motion (which CMAltimeter
is part of) says that the NSMotionUsageDescription
.info.plist
property needs to be defined for all Core Motion service. I have that property in place, but it does not seem to make a difference.
Note that the following is a work-around. I urge everybody to file a bug-report with Apple, to make sure there is pressure on Apple to fix this.
First of all, the NSMotionUsageDescription
key must be defined in the app's .info.plist
file.
Others have suggested the CMSensorRecorder
work-around. It turns out that the "Fitness Tracking" setting in the Settings App needs to be enabled for that to work.
When the authorizationStatus
is .restricted,
then the user first needs to switch on Settings > "Privacy & Security" > "Motion & Fitness" > "Fitness Tracking"
When the authorizationStatus
is .notDetermined,
then start the CMSensorRecorder
. A "Motion & Fitness" privacy settings will be added to your app's settings, and the user will be asked to authorise by iOS. When the user accepts, authorizationStatus
changes to .authorized
and you can start the CMAltimeter.
When the authorizationStatus
is .denied,
the user needs to switch on the "Motion & Fitness" privacy setting of your app.
The following code worked for me:
let status = CMAltimeter.authorizationStatus()
switch status {
case .notDetermined:
// trigger a authorization popup
let recorder = CMSensorRecorder()
DispatchQueue.global().async {
recorder.recordAccelerometer(forDuration: 0.1)
}
case .restricted:
popupText = "Please switch \"Fitness Tracking\" on, in the Apple Settings app, under \"Privacy & Security\" > \"Motion & Fitness\""
showingPopup = true
case .denied:
popupText = "Please switch \"Motion & Fitness\" on, in the app settings"
showingPopup = true
default:
print("authorized")
}
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
let status = CMAltimeter.authorizationStatus()
if status == .authorized {
timer.invalidate()
self.altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) { (data, _error) in
// handle altimeter data
}
}
}