You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:13:24