Добавить значение к переменной внутри замыкания в Swift
Я новичок в быстром языке, и у меня есть проблема, которую я не могу решить.
После запуска моего приложения я получаю вывод пустой строки: ноль
Итак, мой вопрос, как добавить значение к переменной внутри замыкания?
Потому что, когда я добавляю строку в печать замыкания (self.latLong), я получаю вывод координат, но мне нужно это значение внутри переменной, потому что мне нужно манипулировать этой переменной позже в моем коде, и я не хочу писать все функции внутри это закрытие
Это мой код:
import UIKit
import CoreLocation
import Firebase
var latLong: String!
override func viewDidLoad() {
super.viewDidLoad()
findCordiante(adress: "Cupertino, California, U.S.")
print(latLong)
}
func findCordiante(adress:String){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(adress) {
placemarks, error in
if (placemarks != nil){
let placemark = placemarks?.first
let lat = placemark?.location?.coordinate.latitude
let lon = placemark?.location?.coordinate.longitude
self.latLong = String(describing: lat!) + "," + String(describing: lon!)
}else{
//handle no adress
self.latLong = ""
}
}
}
2 ответа
Проблема в том, что geocodeAddressString
работает асинхронно (то есть требуется так много времени, что они написали его для немедленного возврата и вызова его закрытия позже, когда запрос будет выполнен), поэтому viewDidLoad
печатает latLong
задолго до того, как это свойство было в конечном итоге установлено в geocodeAddressString
закрытие обработчика завершения.
Решение состоит в том, чтобы принять шаблон асинхронного программирования в своем собственном коде. Например, используйте свой собственный шаблон обработчика завершения:
override func viewDidLoad() {
super.viewDidLoad()
findCordiante(adress: "Cupertino, California, U.S.") { string in
// use `string` here ...
if let string = string {
self.latLong = string
print(string)
} else {
print("not found")
}
}
// ... but not here, because the above runs asynchronously and it has not yet been set
}
func findCordiante(adress:String, completionHandler: @escaping (String?) -> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(adress) { placemarks, error in
if let location = placemarks?.first?.location, location.horizontalAccuracy >= 0 {
completionHandler("\(location.coordinate.latitude), \(location.coordinate.longitude)")
} else {
completionHandler(nil)
}
}
}
LatLong это nil
так как print(latLong)
вызывается сразу после загрузки представления, до значения latLong
установлено. Вы можете определить функцию для обработки latLong
и назовите это в закрытии.
import UIKit
import CoreLocation
import Firebase
var latLong: String!
override func viewDidLoad() {
super.viewDidLoad()
findCordiante(adress: "Cupertino, California, U.S.")
print(latLong)
}
func findCordiante(adress:String){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(adress) {
placemarks, error in
if (placemarks != nil){
let placemark = placemarks?.first
let lat = placemark?.location?.coordinate.latitude
let lon = placemark?.location?.coordinate.longitude
self.latLong = String(describing: lat!) + "," + String(describing: lon!)
//Do something with latLong now
self.doSomething(withlatLong: self.latLong)
}else{
//handle no adress
self.latLong = ""
}
}
}
private func doSomething(withlatLong latLong:String) {
//Do whatever you want with latLong
print(latLong)
}