Search code examples
iosiphonemapkitcllocation

CLFloor returns level 2146959360?


I’m using CLLocationManager, looking at the location property and examining the level of the floor, if any. The documentation suggests that if it couldn’t determine the floor, that it would just return nil. In practice, I am getting a CLFloor instance, but its level is 2146959360. Converting that to hex, 0x7FF80000, which looks suspiciously like some cryptic sentinel value.

lazy var locationManager: CLLocationManager = {
    let locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    return locationManager
}()

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    switch CLLocationManager.authorizationStatus() {
    case .notDetermined: locationManager.requestWhenInUseAuthorization()
    case .denied:        redirectToSettings()
    default:             break
    }
}

@IBAction func didTapGetLocation(_ sender: Any) {
    updateLabels(for: locationManager.location)
}

func updateLabels(for location: CLLocation?) {
    guard let location = location else {
        floorLabel.text = "No location."
        return
    }

    if let floor = location.floor {
        let hexString = "0x" + String(format: "%08x", floor.level)
        floorLabel.text = "\(floor.level) (\(hexString))"
    } else {
        floorLabel.text = "No floor."
    }
}

I’m seeing this behavior in on a physical iOS 13.3.1 devices, only. FWIW, older iOS versions (I’ve only got iOS 10 device sitting here) appear to return nil, as expected, as does the simulator.

What’s going on?


Solution

  • This problem goes away if you call startUpdatingLocation. If you do that, then the floor property will be nil. This CLFloor instance with a level value of 2146959360 (0x7FF80000) only appears if you query the location of the CLLocationManager without having first called startUpdatingLocation.

    The documentation suggests that this location property is populated with the last known value. Regardless, the floor should be nil (for my particular location, at least) but isn’t. The level is invalid.

    See this repo for example of manifestation of the bug and demonstration of how calling startUpdatingLocation works.

    enter image description here

    I’ve filed a bug report (FB7638281).