Swift异步逆地理编码获取地址无法返回至saveButton方法问题求助
问题根因
CLGeocoder.reverseGeocodeLocation 是异步方法,不会立刻执行完成,你当前写的同步返回String的getLocation()方法,在逆地理编码的闭包还没返回结果的时候就已经执行结束了,所以永远拿不到地址值。闭包内部的return addr只是结束闭包本身的执行,并不会把值返回到getLocation()的调用方。
解决方案
方案1:闭包回调实现(兼容iOS 11+)
先改造getLocation方法,去掉同步返回,改为通过逃逸闭包回传地址结果:
func getLocation(completion: @escaping (String) -> Void) { // 获取坐标 let result = lm.getLocationCoordinates() entryLat = result.0 entryLong = result.1 let location = CLLocation(latitude: entryLat, longitude: entryLong) location.placemark { placemark, error in guard let placemark = placemark, let address = placemark.postalAddressFormatted else { print("Error:", error ?? "nil") completion("Unknown") return } print("formatted address: \(address)") completion(address) } }
再改造saveButton方法,将Core Data保存逻辑移到闭包内部,等拿到地址后再执行:
func saveButton() { getLocation { [weak self] address in guard let self = self else { return } self.addr = address print("addr = \(address)") // 保存条目到Core Data let newEntry = CurrTrans(context: self.viewContext) newEntry.id = UUID() newEntry.entryDT = self.entryDT newEntry.entryDsc = self.entryDsc newEntry.moneyD = self.moneyD newEntry.entryLat = self.entryLat newEntry.entryLong = self.entryLong newEntry.address = address do { try self.viewContext.save() print("newEntry.address = \(newEntry.address ?? "")") } catch { print(error.localizedDescription) } } }
方案2:async/await实现(iOS 15+ 推荐)
语法更简洁,避免回调嵌套:
首先给CLLocation扩展新增异步方法:
extension CLLocation { func getPlacemark() async throws -> CLPlacemark? { return try await CLGeocoder().reverseGeocodeLocation(self).first } }
改造saveButton方法,用Task包裹异步逻辑:
func saveButton() { // 先获取坐标 let result = lm.getLocationCoordinates() entryLat = result.0 entryLong = result.1 let location = CLLocation(latitude: entryLat, longitude: entryLong) Task { do { guard let placemark = try await location.getPlacemark(), let address = placemark.postalAddressFormatted else { self.addr = "Unknown" return } self.addr = address // 保存到Core Data let newEntry = CurrTrans(context: self.viewContext) newEntry.id = UUID() newEntry.entryDT = entryDT newEntry.entryDsc = entryDsc newEntry.moneyD = moneyD newEntry.entryLat = entryLat newEntry.entryLong = entryLong newEntry.address = address try viewContext.save() print("newEntry.address = \(newEntry.address ?? "")") } catch { print("逆地理编码错误: \(error.localizedDescription)") } } }
注意事项
- 苹果对逆地理编码接口有调用频率限制,短时间内发起过多请求会返回错误,建议做好防抖或本地缓存逻辑。
- Core Data的保存操作必须在对应context的队列执行,如果你使用的是主队列context,上述写法无需额外调整。
内容的提问来源于stack exchange,提问作者Galen Smith
相关产品推荐
相关产品推荐

