代码在 swift 中完成 运行 之前的函数 returns
Function returns before code finishes running in swift
我创建了一个 class 函数,其中包含一个将位置坐标反向地理编码为地址字符串的闭包。我最初是用 viewcontroller 编写的,但我需要 运行 将这段代码写在几个地方。
我的问题是class函数returns闭包前的字符串运行s,所以返回的字符串是空的。我有什么方法可以解决这个问题?还有比使用 class 函数更好的方法来组织我的代码吗?
import CoreLocation
class LocationUtil: CLLocation {
class func getLocationAddress(location:CLLocation?) -> NSString {
var geocoder = CLGeocoder()
var addressString : String = ""
if location != nil {
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
var placemark:CLPlacemark!
if error == nil && placemarks.count > 0 {
placemark = placemarks[0] as CLPlacemark
if placemark.subThoroughfare != nil {
addressString = placemark.subThoroughfare + " "
}
if placemark.thoroughfare != nil {
addressString = addressString + placemark.thoroughfare + ", "
}
if placemark.locality != nil {
addressString = addressString + placemark.locality + ", "
}
if placemark.administrativeArea != nil {
addressString = addressString + placemark.administrativeArea + " "
}
if placemark.postalCode != nil {
addressString = addressString + placemark.postalCode + " "
}
if placemark.country != nil {
addressString = addressString + placemark.country
}
}
println("Address in closure: \(addressString)") //prints addresss
})
}
println("Address out of closure: \(addressString)") // doesn't print address
return addressString //this returns nothing
}
}
你应该 return 你的
里面的 completionHandler
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
函数结束时会调用completionHandler
。为此,您还应该异步创建自己的函数 return。
这是必需的,因为您的 reverseGeocodeLocation
函数是 运行 异步的。您的主线程将继续 运行 您的 getLocationAddress
因此它将 return 字符串但它是空的,因为它是 return 在异步函数完成之前编辑的。
geocoder.reverseGeocodeLocation
异步运行 并仅在 完成后调用 completionHandler
.
因此,获得 return 值显然不是一种选择。相反,接受闭包作为 input/argument 用于 class 函数
class func getLocationAddress(location: CLLocation, getLocCompletionHandler : (addressString : String?, error : NSError?) -> Void) {
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
//Your current code
//...
//...
println("Address: \(addressString)")
//Instead of returning the address string, call the 'getLocCompletionHandler'
getLocCompletionHandler(addressString: addressString, error: error)
})
}
并且当您调用此函数时,不要使用 return 值,而是等待闭包被调用:
LocationUtil.getLocationAddress(currentLocation, completionHandler: { (addressObject, error) -> Void in
println("Address: \(addressString)")
//OR handle the error appropriately
}
继续阅读 closures 以更好地理解这个概念。
就代码组织而言,class 函数在这种情况下是一个不错的选择。
我创建了一个 class 函数,其中包含一个将位置坐标反向地理编码为地址字符串的闭包。我最初是用 viewcontroller 编写的,但我需要 运行 将这段代码写在几个地方。
我的问题是class函数returns闭包前的字符串运行s,所以返回的字符串是空的。我有什么方法可以解决这个问题?还有比使用 class 函数更好的方法来组织我的代码吗?
import CoreLocation
class LocationUtil: CLLocation {
class func getLocationAddress(location:CLLocation?) -> NSString {
var geocoder = CLGeocoder()
var addressString : String = ""
if location != nil {
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
var placemark:CLPlacemark!
if error == nil && placemarks.count > 0 {
placemark = placemarks[0] as CLPlacemark
if placemark.subThoroughfare != nil {
addressString = placemark.subThoroughfare + " "
}
if placemark.thoroughfare != nil {
addressString = addressString + placemark.thoroughfare + ", "
}
if placemark.locality != nil {
addressString = addressString + placemark.locality + ", "
}
if placemark.administrativeArea != nil {
addressString = addressString + placemark.administrativeArea + " "
}
if placemark.postalCode != nil {
addressString = addressString + placemark.postalCode + " "
}
if placemark.country != nil {
addressString = addressString + placemark.country
}
}
println("Address in closure: \(addressString)") //prints addresss
})
}
println("Address out of closure: \(addressString)") // doesn't print address
return addressString //this returns nothing
}
}
你应该 return 你的
里面的completionHandler
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
函数结束时会调用completionHandler
。为此,您还应该异步创建自己的函数 return。
这是必需的,因为您的 reverseGeocodeLocation
函数是 运行 异步的。您的主线程将继续 运行 您的 getLocationAddress
因此它将 return 字符串但它是空的,因为它是 return 在异步函数完成之前编辑的。
geocoder.reverseGeocodeLocation
异步运行 并仅在 完成后调用 completionHandler
.
因此,获得 return 值显然不是一种选择。相反,接受闭包作为 input/argument 用于 class 函数
class func getLocationAddress(location: CLLocation, getLocCompletionHandler : (addressString : String?, error : NSError?) -> Void) {
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
//Your current code
//...
//...
println("Address: \(addressString)")
//Instead of returning the address string, call the 'getLocCompletionHandler'
getLocCompletionHandler(addressString: addressString, error: error)
})
}
并且当您调用此函数时,不要使用 return 值,而是等待闭包被调用:
LocationUtil.getLocationAddress(currentLocation, completionHandler: { (addressObject, error) -> Void in
println("Address: \(addressString)")
//OR handle the error appropriately
}
继续阅读 closures 以更好地理解这个概念。
就代码组织而言,class 函数在这种情况下是一个不错的选择。