Swift - 在函数之间设置值时遇到 nil 问题

Posted

技术标签:

【中文标题】Swift - 在函数之间设置值时遇到 nil 问题【英文标题】:Swift - Trouble with getting nil when setting values in between functions 【发布时间】:2018-02-13 19:58:08 【问题描述】:

您好,当我编写一个简单的位置接收类时,我似乎只能将 nil 作为我的位置变量。我已经搜索了一段时间的堆栈溢出并尝试了许多解决方案,但我似乎无法修复它。

下面是我的代码。我正在尝试方法,一种是在我的 didUpdateLocations 方法的结构中设置变量。另一种只是更新一个变量userLocation。目前两者都只是给出我的 nil,我不知道为什么。

class SendLocation:  NSObject, CLLocationManagerDelegate


var userLocation: CLLocation? = nil
var locationManager:CLLocationManager!


struct LocationStruct
    var latitude:CLLocationDegrees?, longitude:CLLocationDegrees?


var locationStruct = LocationStruct()


func sendLocationPost()
    determineCurrentLocation()
    print(userLocation) // This is nil
    print(locationStruct.latitude) // This is nil
    print(locationStruct.longitude) // This is nil



func determineCurrentLocation()
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    if CLLocationManager.locationServicesEnabled()
        locationManager.startUpdatingLocation()
    

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    userLocation = locations[0] as CLLocation
    print(userLocation) // This IS NOT nil
    locationStruct.latitude=userLocation?.coordinate.latitude
    locationStruct.longitude=userLocation?.coordinate.longitude


提前感谢您的帮助,因为我知道这将是一些简单/愚蠢的事情

【问题讨论】:

您何时何地致电sendLocationPost 哪个先打印,nil 还是 non-nil? @PhillipMills Mills 既然你提到了它,那么 nils 打印首先 有道理。在致电didUpdateLocations 之前,您不能假设位置已更新。 【参考方案1】:

这只是理解事情需要时间的问题。您正在向前迈进,就好像开始获取位置时会立即为您提供位置。但它没有:

func sendLocationPost()
    determineCurrentLocation()
    // so now things start... but they take _time_...!
    print(userLocation) // This is nil
    // because it's _too soon!_
    // ...

当您第一次拨打determineCurrentLocation 时,传感器需要很长时间才能预热并到达合适的位置:

func determineCurrentLocation()
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    if CLLocationManager.locationServicesEnabled()
        locationManager.startUpdatingLocation()
        // SLOWLY... things now start to happen
    

最后,经过一段重要的时间,也许,只是也许,我们终于开始得到一些更新,再过一段时间,也许它们不是零:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    userLocation = locations[0] as CLLocation
    print(userLocation) // This IS NOT nil
    locationStruct.latitude=userLocation?.coordinate.latitude
    locationStruct.longitude=userLocation?.coordinate.longitude


现在我们找到了位置。但与此同时,您在sendLocationPost 中的代码很久以前就结束了,并得到了nil

【讨论】:

这是一个非常好的答案,谢谢。我没想到 startUpdatingLocations() 会花时间。 比获取位置更重要的是它是异步发生的,所以执行可以在发生时继续。 @BallpointBen 这就是我所说的“花时间”的意思。 “异步”的意思实际上仅此而已。正如我的回答所示,我们在sendLocationPost 中继续下一步determineCurrentLocation 开始的操作有机会更新位置之前。 异步具体表示执行不会阻塞当前线程。冗长的任务不需要异步执行。 @BallpointBen 是的,这是真的。但我更愿意在与一个明确的初学者打交道时进行解释,而不是用不必要的技术性措辞让他雪上加霜。

以上是关于Swift - 在函数之间设置值时遇到 nil 问题的主要内容,如果未能解决你的问题,请参考以下文章

Swift/Xcode 9 - 应用内购买 - 在展开可选值时意外发现 nil

Swift 和 UILabel - 致命错误:在展开可选值时意外发现 nil

Swift - 在展开可选值时意外发现 nil - 从委托调用变量

Swift 3.0 - 核心数据 / 意外发现 nil

iOS Swift IBKS 信标错误:线程 1:致命错误:在展开可选值时意外发现 nil

Swift:致命错误:在展开可选值时意外发现 nil