如何在闭包中调用函数
How To Call a func within a Closure
在模型的classLocation
中,我得到了当前城市的名称:
var currentLatitude: Double!
var currentLongitude: Double!
var currentLocation: String!
var currentCity: String!
func getLocationName() {
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
})
}
在视图控制器中,我想更新 UI 并更新我的标签以显示当前城市。
但是,self.currentCity = city
发生在闭包内部。因此,如果我只是 运行 视图控制器中的一个函数:
func updateUI() {
cityLbl.text = Location.sharedInstance.currentCity
}
- 我无处可去,因为关闭尚未完成 运行ning。
有人建议我向
getLocationName()
添加一个完成处理程序,并在其中执行对将更新 UI 的函数的调用。
然而,从所有关于闭包、完成处理程序的教程中,我不清楚如何实现它。
如何构造完成处理程序,将其作为参数传递给 getLocationName()
以及如何从视图控制器调用 getLocationName
?
要处理这种情况,您有多种选择。
使用您的位置创建 delegate/protocol
class
- 创建一个协议并使用您的
ViewController
实现该协议方法,并在您的 Location
class 中声明其实例。然后在 reverseGeocodeLocation
的 completionHandler
中调用此委托方法。查看 Protocol
上的 Apple 文档了解更多详情。
您可以使用 Location
class 的 getLocationName
方法创建 completionHandler
。
用 getLocationName
添加 completionHandler
并像这样在 reverseGeocodeLocation
的 completionHandler
中调用 completionHandler
。
func getLocationName(completionHandler: @escaping (_ success: Bool) -> Void) {
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
completionHandler(false)
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
completionHandler(true)
//self.nowUpdateUI()
})
}
现在在 ViewController
调用此函数的地方调用完成块内的 updateUI
方法。
Location.sharedInstance.getLocationName { (success) in
if success {//If successfully got response
self.updateUI()
}
}
您可以为(NS)NotificationCenter
添加观察者。
- 用
(NS)NotificationCenter
注册观察者,然后 post reverseGeocodeLocation
的 completionHandler
内的通知。您可以通过 Whosebug Post. 获得更多详细信息
你的整段代码:
completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
}
)
已经 发生在 completionHandler 中(在一切完成后发生)还有 运行 你的 updateUI()
在 completionHandler 中。所以你的结束代码是:
completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
DispatchQueue.main.async {
updateUI()
}
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
}
)
你必须使用 DispatchQueue.main
的原因是因为你的 completionHandler 在后台队列上,但你必须始终从你的 mainQueue 中做你 UI 相关的事情——这样用户在他们的 UI 没有任何故障。想象一下,如果您在后台线程上执行操作并且速度很慢
// I thing issue back ground thread you need to update your UI in main thread
var currentLatitude: Double!
var currentLongitude: Double!
var currentLocation: String!
var currentCity: String!
func getLocationName() {
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
DispatchQueue.main.async {
self.nowUpdateUI()
// Update your UI in main thread
}
})
}
在模型的classLocation
中,我得到了当前城市的名称:
var currentLatitude: Double!
var currentLongitude: Double!
var currentLocation: String!
var currentCity: String!
func getLocationName() {
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
})
}
在视图控制器中,我想更新 UI 并更新我的标签以显示当前城市。
但是,self.currentCity = city
发生在闭包内部。因此,如果我只是 运行 视图控制器中的一个函数:
func updateUI() {
cityLbl.text = Location.sharedInstance.currentCity
}
- 我无处可去,因为关闭尚未完成 运行ning。
有人建议我向
getLocationName()
添加一个完成处理程序,并在其中执行对将更新 UI 的函数的调用。 然而,从所有关于闭包、完成处理程序的教程中,我不清楚如何实现它。 如何构造完成处理程序,将其作为参数传递给getLocationName()
以及如何从视图控制器调用getLocationName
?
要处理这种情况,您有多种选择。
使用您的位置创建
delegate/protocol
class- 创建一个协议并使用您的
ViewController
实现该协议方法,并在您的Location
class 中声明其实例。然后在reverseGeocodeLocation
的completionHandler
中调用此委托方法。查看Protocol
上的 Apple 文档了解更多详情。
- 创建一个协议并使用您的
您可以使用
Location
class 的getLocationName
方法创建completionHandler
。用
getLocationName
添加completionHandler
并像这样在reverseGeocodeLocation
的completionHandler
中调用completionHandler
。func getLocationName(completionHandler: @escaping (_ success: Bool) -> Void) { let geoCoder = CLGeocoder() let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude) geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in guard let addressDict = placemarks?[0].addressDictionary else { completionHandler(false) return } if let city = addressDict["City"] as? String { self.currentCity = city print(city) } if let zip = addressDict["ZIP"] as? String { print(zip) } if let country = addressDict["Country"] as? String { print(country) } completionHandler(true) //self.nowUpdateUI() }) }
现在在
ViewController
调用此函数的地方调用完成块内的updateUI
方法。Location.sharedInstance.getLocationName { (success) in if success {//If successfully got response self.updateUI() } }
您可以为
(NS)NotificationCenter
添加观察者。- 用
(NS)NotificationCenter
注册观察者,然后 postreverseGeocodeLocation
的completionHandler
内的通知。您可以通过 Whosebug Post. 获得更多详细信息
- 用
你的整段代码:
completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
}
)
已经 发生在 completionHandler 中(在一切完成后发生)还有 运行 你的 updateUI()
在 completionHandler 中。所以你的结束代码是:
completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
DispatchQueue.main.async {
updateUI()
}
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
self.nowUpdateUI()
}
)
你必须使用 DispatchQueue.main
的原因是因为你的 completionHandler 在后台队列上,但你必须始终从你的 mainQueue 中做你 UI 相关的事情——这样用户在他们的 UI 没有任何故障。想象一下,如果您在后台线程上执行操作并且速度很慢
// I thing issue back ground thread you need to update your UI in main thread
var currentLatitude: Double!
var currentLongitude: Double!
var currentLocation: String!
var currentCity: String!
func getLocationName() {
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
if let city = addressDict["City"] as? String {
self.currentCity = city
print(city)
}
if let zip = addressDict["ZIP"] as? String {
print(zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
DispatchQueue.main.async {
self.nowUpdateUI()
// Update your UI in main thread
}
})
}