异步地理定位 Return
Asynchronous GeoLocation Return
使用 locationManager 的坐标,我想在底部显示通过反向 geoLocation 获得的位置(地址)的地图。坐标和地图显示正确,但我无法生成地址。我正在尝试遵循 iOS 11 或更高版本 部分中 处的示例代码。示例中显示的两个扩展(CLPlacemark 和 CLLocation)与我使用的相同。所以看起来,虽然我遵循示例用法,但我没有正确处理异步 Placemark 函数。函数 getLocation() 正确显示地址,但它没有返回到 saveButton()。
任何有关异步函数的帮助 return 将不胜感激。
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([=12=]?.first, ) }
}
}
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)
}
}
您的代码无法编译。当您尝试 return
addr` 时,编译器会发出有关 Unexpected non-void return value in void function
的警告,因为闭包具有非空 return 类型。
而是使用完成处理程序。
这可能看起来像这样:
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
中还缺少 }
使用 locationManager 的坐标,我想在底部显示通过反向 geoLocation 获得的位置(地址)的地图。坐标和地图显示正确,但我无法生成地址。我正在尝试遵循 iOS 11 或更高版本 部分中
任何有关异步函数的帮助 return 将不胜感激。
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([=12=]?.first, ) }
}
}
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)
}
}
您的代码无法编译。当您尝试 return
addr` 时,编译器会发出有关 Unexpected non-void return value in void function
的警告,因为闭包具有非空 return 类型。
而是使用完成处理程序。
这可能看起来像这样:
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
}