Добавить значение к переменной внутри замыкания в 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)
}
Другие вопросы по тегам