iOS开发:如何将CLLocationCoordinate2D转为自定义Coordinates结构体
解决CLLocationCoordinate2D转自定义Coordinates结构体及闭包赋值问题
首先,先解决类型转换的问题——把CLLocationCoordinate2D转成你自定义的Coordinates结构体其实非常直接,因为两者都是存储经纬度的数值类型,直接用前者的属性初始化后者就行:
// 当你在闭包里拿到CLLocationCoordinate2D类型的coordinate后 let convertedCoordinates = Coordinates( latitude: coordinate.latitude, longitude: coordinate.longitude )
接下来是你遇到的核心问题:闭包里无法给常量赋值。这是因为你定义的coordinates是let常量,它只能被初始化一次,而getCoordinateFrom是异步方法,闭包会在之后的某个时间点才执行,这时候常量已经被固定下来了,自然没法修改。解决这个问题有两种常见的思路:
1. 把常量改成变量
最直接的方式就是把let coordinates改成var变量,要么给个默认值,要么定义成可选类型:
方式一:带默认值的变量
// 定义成变量,给个初始默认值 var coordinates = Coordinates(latitude: 0.0, longitude: 0.0) @IBAction func changeCityButtonPressed(_ sender: UIButton) { guard let address = textField.text else { return } getCoordinateFrom(address: address) { coordinate, error in guard let coordinate = coordinate, error == nil else { return } DispatchQueue.main.async { // 直接赋值给变量 self.coordinates = Coordinates( latitude: coordinate.latitude, longitude: coordinate.longitude ) print(self.coordinates) } } }
方式二:可选类型变量
如果初始时不需要默认值,可以定义成可选类型,避免不必要的初始值:
// 可选类型,初始为nil var coordinates: Coordinates? @IBAction func changeCityButtonPressed(_ sender: UIButton) { guard let address = textField.text else { return } getCoordinateFrom(address: address) { coordinate, error in guard let coordinate = coordinate, error == nil else { return } DispatchQueue.main.async { self.coordinates = Coordinates( latitude: coordinate.latitude, longitude: coordinate.longitude ) print(self.coordinates ?? "未获取到坐标") } } }
2. 用闭包回调传递结果(更灵活的方式)
如果你不想把coordinates改成变量(比如遵循不可变数据的设计思路),可以在获取到转换后的坐标后,通过另一个闭包把结果传递出去,用于更新UI或者其他逻辑:
// 给changeCityButtonPressed添加一个回调参数,或者在内部处理 @IBAction func changeCityButtonPressed(_ sender: UIButton) { guard let address = textField.text else { return } getCoordinateFrom(address: address) { coordinate, error in guard let coordinate = coordinate, error == nil else { return } let convertedCoords = Coordinates( latitude: coordinate.latitude, longitude: coordinate.longitude ) DispatchQueue.main.async { // 这里可以直接用convertedCoords做后续操作,比如更新UI self.updateUI(with: convertedCoords) } } } // 专门的UI更新方法 private func updateUI(with coords: Coordinates) { print("当前坐标:\(coords.latitude), \(coords.longitude)") // 比如更新标签文本、调用天气接口等 }
额外小技巧:给CLLocationCoordinate2D加扩展
为了让类型转换更优雅,你可以给CLLocationCoordinate2D写一个扩展,直接生成Coordinates实例:
extension CLLocationCoordinate2D { func toCoordinates() -> Coordinates { return Coordinates(latitude: latitude, longitude: longitude) } }
这样在闭包里就可以直接写:
let convertedCoords = coordinate.toCoordinates()
是不是简洁多了?
内容的提问来源于stack exchange,提问作者Over
相关产品推荐
相关产品推荐

