【问题标题】:Asynchronous GeoLocation Return异步地理位置返回
【发布时间】:2021-10-25 20:02:59
【问题描述】:

使用来自 locationManager 的坐标,我想显示一张地图,底部的位置(地址)是通过反向 geoLocation 获得的。坐标和地图显示正确,但我无法生成地址。我正在尝试遵循 iOS 11 或更高版本部分中Find city name and country from latitude and longitude in Swift 的示例代码。示例中显示的两个扩展(CLPlacemark 和 CLLocation)与我使用的相同。因此,尽管我遵循示例用法,但似乎没有正确处理异步 Placemark 函数。函数 getLocation() 正确显示地址,但没有返回 saveButton()。

任何有关异步函数返回的帮助将不胜感激。

struct EntryView: View {
    @Environment(\.managedObjectContext) var viewContext    // core data
    @ObservedObject private var lm = LocationManager()      // location

    @State private var entryLat: Double = 0.0
    @State private var entryLong: Double = 0.0
    @State private var addr: String = ""
    
    var body: some View {
        
        GeometryReader { g in
            
            List {  

              Button(action: {
                    self.saveButton()   // save entry button pressed
                }) {
                    HStack {
                        Spacer()
                        Text ("Save")
                        Spacer()
                    }
                }
        }
        .navigationBarHidden(true)
        .navigationViewStyle(StackNavigationViewStyle())
    }

    // the save button has been pressed
    func saveButton() {
        
        // get coordinates and address
        let addr = getLocation()
        print("addr = \(addr)")  // nothing displayed here except addr
        
        // save entry to core data
        let newEntry = CurrTrans(context: viewContext)
        
        newEntry.id = UUID()                            
        newEntry.entryDT = entryDT         // entry date
        newEntry.entryDsc = entryDsc       // entry description                      
        newEntry.moneyD = moneyD           // money as double
        
        newEntry.entryLat = entryLat       // store location for maps
        newEntry.entryLong = entryLong
        
        newEntry.address = addr           // formatted address
        print("newEntry.address = \(newEntry.address ?? "")")  
        
        do {
            try viewContext.save()
            
        } catch {
            print(error.localizedDescription)
        }
    }

    func getLocation() -> String {
 
        // get location coordinates
        let result = lm.getLocationCoordinates()
        entryLat = result.0
        entryLong = result.1
        
        // get location address
        let location = CLLocation(latitude: entryLat, longitude: entryLong)
        location.placemark { placemark, error in
            guard let placemark = placemark else {
                print("Error:", error ?? "nil")
                return
            }
            
            print("formatted address: \(placemark.postalAddressFormatted ?? "")")
            addr = placemark.postalAddressFormatted ?? "Unknown"
            return addr
        }
    }
}

下面的代码是位置管理器的一部分。

extension CLLocation {
    func placemark(completion: @escaping (_ placemark: CLPlacemark?, _ error: Error?) -> ()) {
        CLGeocoder().reverseGeocodeLocation(self) { completion($0?.first, $1) }
    }
}

extension CLPlacemark {
    /// street name, eg. Infinite Loop
    var streetName: String? { thoroughfare }
    /// // eg. 1
    var streetNumber: String? { subThoroughfare }
    /// city, eg. Cupertino
    var city: String? { locality }
    /// neighborhood, common name, eg. Mission District
    var neighborhood: String? { subLocality }
    /// state, eg. CA
    var state: String? { administrativeArea }
    /// county, eg. Santa Clara
    var county: String? { subAdministrativeArea }
    /// zip code, eg. 95014
    var zipCode: String? { postalCode }
    /// postal address formatted
   
    var postalAddressFormatted: String? {
        guard let postalAddress = postalAddress else { return nil }
        return CNPostalAddressFormatter().string(from: postalAddress)
    }
}

【问题讨论】:

  • 对不起,我删除了一些与手头问题无关的代码

标签: swiftui ios14 xcode12


【解决方案1】:

您的代码无法编译。当您尝试 return addr` 时,编译器会发出关于 Unexpected non-void return value in void function 的警告,因为闭包具有非 void 返回类型。

改为使用完成处理程序。

这可能看起来像这样:

func getLocation(completion: @escaping (String) -> Void) {
    // get location coordinates
    let result = lm.getLocationCoordinates()
    entryLat = result.0
    entryLong = result.1
    
    // get location address
    let location = CLLocation(latitude: entryLat, longitude: entryLong)
    location.placemark { placemark, error in
        guard let placemark = placemark else {
            print("Error:", error ?? "nil")
            return
        }
        
        print("formatted address: \(placemark.postalAddressFormatted ?? "")")
        addr = placemark.postalAddressFormatted ?? "Unknown"
        completion(addr)
    }
}

还有,之前在saveButton

func saveButton() {
    
    // get coordinates and address
    getLocation { addr in
        print("addr = \(addr)")
        self.addr = addr
        //do your CoreData code that depends on addr here
    }
    //don't try to use addr here, outside the completion handler
}

您的body 中还缺少}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2019-10-14
    • 1970-01-01
    相关资源
    最近更新 更多