iOS 27:在访问CLLocationManager.authorizationStatus() 时,应用会冻结

移动开发 2026-07-08
  • 我遇到了一个奇怪的问题,这个问题只在iOS 27上出现。
  • 我有一个基本的 LocationManager 实现:

``` import Foundation import CoreLocation import UIKit

class LocationManager: NSObject, CLLocationManagerDelegate {

  static let shared = LocationManager()

  private let manager = CLLocationManager()
  private let geocoder = CLGeocoder()

  // MARK: - Public API
  func fetchLocationIfNeeded() {

      manager.delegate = self

      handleAuthorization(CLLocationManager.authorizationStatus())
  }

  private func handleAuthorization(_ status: CLAuthorizationStatus) {

      switch status {
      case .notDetermined:
          manager.requestWhenInUseAuthorization()

      case .restricted, .denied:
          showLocationPermissionAlert()
      case .authorizedWhenInUse, .authorizedAlways:
          manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
          manager.requestLocation()

      @unknown default:
          break
      }
  }

  private func showLocationPermissionAlert() {
      let alertController = UIAlertController(
          title: "Location Access Required",
          message: "Please enable location access in Settings to use this feature.",
          preferredStyle: .alert
      )

      alertController.addAction(UIAlertAction(title: "Open Settings", style: .default, handler: { _ in
          if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
              UIApplication.shared.open(settingsURL)
          }
      }))

      if let topController = UIApplication.shared.windows.first?.rootViewController {
          topController.present(alertController, animated: true)
      }
  }

  func locationManager(_ manager: CLLocationManager,
                       didChangeAuthorization status: CLAuthorizationStatus) {
      handleAuthorization(status)
  }

  // MARK: - Location
  func locationManager(_ manager: CLLocationManager,
                       didUpdateLocations locations: [CLLocation]) {

      guard let location = locations.first else { return }

      geocoder.reverseGeocodeLocation(location) {
          placemarks,
          error in

          guard error == nil,
                let postalCode = placemarks?.first?.postalCode,
                !postalCode.isEmpty else { return }

          print("zipcode :", postalCode)
          globalZipCode = postalCode

              NotificationCenter.default.post(
                  name: NSNotification.Name("ZipcodeGet"),
                  object: nil
              )
      }
  }

  func locationManager(_ manager: CLLocationManager,
                       didFailWithError error: Error) {
      print("Location error: ", error.localizedDescription)
  }

} `` * 在 iOS 27 上,应用在进入handleAuthorization(_:)` 之前似乎会冻结。 * 看起来触发问题的那一行是:

handleAuthorization(CLLocationManager.authorizationStatus()) * 在调试器中检查该值时,第一次得到的输出是:

po CLLocationManager.authorizationStatus() warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available. * 再次运行相同的命令会得到:

po CLLocationManager.authorizationStatus() __C.CLAuthorizationStatus * 我已经确认需要的权限键存在于 Info.plist

<key>NSLocationWhenInUseUsageDescription</key> <string>We use your location to determine your ZIP code.</string> * 相同的实现对较旧的应用可以正常工作,但这个项目在iOS 27上才会出现问题。 * 有没有人遇到过类似的问题,或者知道在iOS 27中对 CLLocationManager.authorizationStatus() 或定位授权处理有任何变化吗?

解决方案

  • 经过大量调试,我发现问题似乎与直接操作由 CLAuthorizationStatus 枚举返回的值有关:
CLLocationManager.authorizationStatus().rawValue
  • 作为一个变通办法,我把 fetchLocationIfNeeded() 从:
handleAuthorization(CLLocationManager.authorizationStatus())
  • 改为:
        let status = CLLocationManager.authorizationStatus().rawValue

        switch status {
        case CLAuthorizationStatus.notDetermined.rawValue: // notDetermined
            manager.requestWhenInUseAuthorization()

        case CLAuthorizationStatus.restricted.rawValue,
            CLAuthorizationStatus.denied.rawValue: // restricted, denied
            showLocationPermissionAlert()

        case CLAuthorizationStatus.authorizedAlways.rawValue,
            CLAuthorizationStatus.authorizedWhenInUse.rawValue: // authorizedAlways, authorizedWhenInUse
            manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
            manager.requestLocation()

        default:
            break
        }
  • 这个变通方法在较旧的iOS版本和iOS 27上都能正确工作。

原始值代表的含义

  • CLLocationManager.authorizationStatus().rawValue 返回一个 Int32 值:
0 = notDetermined 
1 = restricted 
2 = denied 
3 = authorizedAlways 
4 = authorizedWhenInUse
  • 因此,你也可以使用基于整型的switch:
switch status {
case 0:  // notDetermined
    manager.requestWhenInUseAuthorization()

case 1, 2: // restricted, denied
    break

case 3, 4: // authorizedAlways, authorizedWhenInUse
    manager.requestLocation()

default:
    break
}
  • 我还测试了使用实例属性:CLLocationManager().authorizationStatus,但那也不起作用。在调试器中对其进行求值时显示为:
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0).
The process has been returned to the state before expression evaluation.
  • 因此,如果你在iOS 27上遇到这个问题,使用 CLLocationManager.authorizationStatus().rawValue 并与原始整数值进行比较,似乎是一个可靠的变通办法,同时也与较旧的iOS版本保持兼容。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章