Переменная Swift, объявленная вне замыкания, обновляется внутри замыкания, но при доступе вне замыкания возвращает значение по умолчанию? - PullRequest
0 голосов
/ 25 апреля 2020

, поэтому я вызываю функцию, которая должна просто возвращать долготу введенного адреса. Я добавлю его сюда, чтобы вы могли посмотреть на него, а затем прокомментирую его после кода:

func getLongitude(address: String) -> Double {
    var longitude: Double = 0.0
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address) {
        placemarks, error in 
        let placemark = placemarks?.first
        longitude = placemark?.location?.coordinate.longitude ?? 0.0
        print("The testing longitude is \(longitude)")
    }
    return longitude
}

Как вы можете видеть, я объявил переменную долготы со значением по умолчанию 0.0. В замыкании внутри функции я обновляю долготу. Оператор print подтверждает, что долгота была обновлена ​​при закрытии функции. Когда к долготе обращаются с помощью оператора return за пределами этого замыкания, он снова возвращает 0.0 (я думаю, что значение долготы не мутирует вне замыкания, но я не знаю, как это исправить). Любая помощь будет высоко ценится!

Ответы [ 2 ]

0 голосов
/ 25 апреля 2020

Закрытие выполняется асинхронно, т.е. после выполнения оператора return. Измените свою функцию на

func getLongitude(address: String, completion: @escaping (Double)->Void)
 {
     var longitude: Double = 0.0
     let geocoder = CLGeocoder()

    geocoder.geocodeAddressString(address)
    {
        placemarks, error in
        let placemark = placemarks?.first
        longitude = placemark?.location?.coordinate.longitude ?? 0.0
        print("The testing longitude is \(longitude)")

        completion(longitude)
    }
 }
0 голосов
/ 25 апреля 2020

Пожалуйста, используйте вкладки, чтобы сделать ваш код более читабельным.

В любом случае geocoder.geocodeAddressString(address) - это метод с обратным вызовом, и в этом методе обратного вызова у вас есть метка. Ваш возврат не будет ждать этого обратного вызова, так как для расчета координат потребуется время, поэтому он возвращает 0.0, которое вы установили в начале. в комментарии:

CLGeocoder() функция geocodeAddressString фактически имеет 2 параметра: адрес и так называемый обратный вызов. Обратный вызов - это просто метод, вызываемый, когда задача (в данном случае вычисление метки) завершается. Swift позволяет вам писать обратный вызов в «быстром» синтаксисе, но на самом деле это выглядит как

geocoder.geocodeAddressString(address, callAfterFinishGeocoding)

func callAfterFinishGeocoding(_ placemark: Placemark) {
   // do stuff with placemark
}

, как вы можете видеть, мы передаем функции геокодирования еще одну функцию, которая будет вызвана после завершения. Параметры callAfterFinishGeocoding определены в geocodeAddressString. Это будет выглядеть примерно так:

callback: @escaping (_ placeMark: Placemark) -> Void

Это будет означать, что обратный вызов должен быть функцией, принимающей метку и возвращающей Void. Перейдите к определению метода и посмотрите, какую функцию он хочет использовать в качестве параметра.

также читайте подробнее здесь: { ссылка }

...