CLLocationManager EXC_BAD_ACCESS 错误

CLLocationManager EXC_BAD_ACCESS error

我遇到了一个奇怪的错误,无法解决这个问题。我制作了一个简单的天气应用程序,可以根据用户坐标更新天气。在模拟器上一切运行完美,但在设备上我收到如下错误。

Imgur

我在 viewDidLoad 正上方的 class 范围内声明了我的位置管理器:

let locationManager = CLLocationManager()

我的 viewDidLoad():

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startMonitoringSignificantLocationChanges()

        tableView.delegate = self
        tableView.dataSource = self

        currentWeather = CurrentWeather()
}

我在 viewDidAppear:

时调用这个函数
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        locationAuthStatus()
    }


func locationAuthStatus() {
    if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
        currentLocation = locationManager.location
        Location.sharedInstance.latitude = currentLocation.coordinate.latitude
        Location.sharedInstance.longitude = currentLocation.coordinate.longitude
        currentWeather.downloadWeatherDetails {
            self.downloadForecastData {
                self.updateMainUI()
            }
        }
    } else {
        locationManager.requestWhenInUseAuthorization()
        locationAuthStatus()
    }
}

如果用户尚未获得授权,则错误是上面 else 语句的第一行。如果您在崩溃后重新运行该应用程序,天气就会更新得很好。任何帮助,将不胜感激。谢谢。

更新

多亏了评论中的建议,我才得以改正我的错误。我将代码从 locationAuthStatus 移到了 locationManager(_ manager: CLLocationManager, didChangeAuthorization.

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
        currentLocation = locationManager.location
        Location.sharedInstance.latitude = currentLocation.coordinate.latitude
        Location.sharedInstance.longitude = currentLocation.coordinate.longitude
        currentWeather.downloadWeatherDetails {
            self.downloadForecastData {
                self.updateMainUI()
            }
        }
    } else {
        locationManager.requestWhenInUseAuthorization()
    }
}

谢谢大家的帮助。

EXEC_BAD_Access 表示取消引用非法内存地址。在这种情况下,内存地址是位置管理器的地址。要诊断问题,我们需要知道位置管理器的创建位置。

由于问题不在显示的代码块本地,而是在设置位置管理器时的某个较早点,因此无法从此处诊断问题。

请提供: 1)初始设置位置管理器属性的地方 2)位置管理器发生变化的任何地方。

还要确保您没有做任何不寻常的事情,例如在不安全的操作(例如 segue)中尝试访问 属性。

确保您的所有权利都已正确配置,并检查堆栈跟踪以查看位置管理器是否正在调用从其下方消失的任何内容。

您是否将 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription 添加到您的 Info.plist 中?

没有这些属性可能会导致设备崩溃

Reference here

我认为您的代码忽略了一些位置操作是异步的。

  1. 您正在调用 requestWhenInUseAuthorization,然后立即进行递归。 requestWhenInUseAuthorization 是异步的,returns 是立即的。在你做递归之前状态不会改变,所以你重复调用它。我怀疑这是导致错误的问题。这里使用didChangeAuthorization
  2. 您使用 locationManager.location 读取位置的方式也很可疑。您应该异步获取位置以获取当前位置。你应该使用 requestLocation()

阅读 CLLocationManagerDelegate 了解如何在 CoreLocation 中处理异步操作