我正在使用CLGeocoder reverseGeocodeLocation。我跑了大约5-10分钟(没有明显的模式)后得到了崩溃并且随机崩溃。这是我的代码:
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
let currentLatCoord = manager.location?.coordinate.latitude
let currentLongCoord = manager.location?.coordinate.longitude
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: currentLatCoord!, longitude: currentLongCoord!)) { (placemarks, error) -> Void in
if error != nil {
print(error)
return
}
let placeArray = placemarks as [CLPlacemark]!
var placeMark: CLPlacemark
placeMark = placeArray![0]
self.locationLabel.text = String(placeMark.addressDictionary?["Thoroughfare"]!)
}
}
而且,只是为了帮助,这里是一条线和错误的图片:
答案 0 :(得分:1)
我认为你需要一些可选的绑定:
if let thoroughfare = placeMark.addressDictionary?["Thoroughfare"] as? String {
self.locationLabel.text = thoroughfare
}
我猜测地址字典中可能没有"Thoroughfare"
键,并且您为nil
的指定初始化程序提供了String
值。
当CLGeocoder
完成其反向地理编码时,您的代码段中的视图是否有可能不在屏幕上(已处置)?如果您将出口定义为隐式展开的可选项:
@IBOutlet var locationLabel : UILabel!
我想知道它是否已经设置为nil
,但由于爆炸(!
),编译器不会让你检查。
但是,当然,如果您的视图在崩溃时仍然在屏幕上,这可能不是问题。
答案 1 :(得分:1)
您向我们提供了代码示例:
let currentLatCoord = manager.location?.coordinate.latitude
let currentLongCoord = manager.location?.coordinate.longitude
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: currentLatCoord!, longitude: currentLongCoord!)) { (placemarks, error) -> Void in
if error != nil {
print(error)
return
}
let placeArray = placemarks as [CLPlacemark]!
var placeMark: CLPlacemark
placeMark = placeArray![0]
self.locationLabel.text = String(placeMark.addressDictionary?["Thoroughfare"]!)
}
如果您使用nil
构造,则可以更优雅地处理if let
值:
CLGeocoder().reverseGeocodeLocation(manager.location!) { placemarks, error in
guard error == nil else {
print(error)
return
}
if let placemark = placemarks?.first {
self.locationLabel.text = placemark.thoroughfare
}
}
当然,如果你反复调用它,我不会每次重新实例化一个新的CLGeocoder
,但希望这说明了这种模式。
但是正如您所看到的,您可以避免从location属性中提取纬度和经度,然后直接使用CLLocation
创建一个新的manager.location
对象。同样,您可以使用thoroughfare
属性,这样您就无需转换addressDictionary
值。
Craig上面提到的关键观察是严格避免使用!
强制解包运算符,除非你肯定变量永远不会是nil
。同样,不要使用[0]
语法,除非您知道数组中至少有一个项目(这就是我使用first
的原因,这是我可以轻松测试的可选项)。
坦率地说,我甚至会确保location
有效(不是nil
且非负horizontalAccuracy
,因为负值表示坐标无效):
if let location = manager.location where location.horizontalAccuracy >= 0 {
CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
guard error == nil else {
print(error)
return
}
if let placemark = placemarks?.first {
self.locationLabel.text = placemark.thoroughfare
}
}
}