Как установить параметр Inout внутри замыкания
Итак, мой вопрос заключается в следующем: я пытаюсь реализовать расширение для CLGeoCoder, чтобы иметь возможность получить название города из CLLocation, но я сталкиваюсь с проблемой, когда пытаюсь установить строку с именем inout city внутри обработчика завершения в reverseGeocodeLocation
Вот мой код для моего расширения:
extension CLGeocoder {
func findCityName(location:CLLocation, inout cityName:String) -> Void{
self.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
// Place details
var placeMark: CLPlacemark!
placeMark = placemarks?[0]
// Address dictionary
print(placeMark.addressDictionary)
// City
if let city = placeMark.addressDictionary!["City"] as? String {
cityName = city
}
})
}
}
Цель этого расширения - установить строку с названием города, передав ее по ссылке на эту функцию.
Примером может быть:
var cityName = ""
let location:CLLocation(latitude: 1, longitude: 1)
let geocoder: CLGeocoder()
geocoder.findCityName(location, &cityName)
///Later on in the process I would want to be able to use cityName for different purposes in my code
Проблема, с которой я сталкиваюсь, заключается в том, что после задания ссылки на cityName в завершение Handler значение cityName остается пустым вне обработчика завершения.
Я новичок в swift, поэтому я, возможно, что-то упустил в указателях или в том, как их использовать, но у меня было понимание, что inout позволит изменить значение переменной внутри функции или обработчика закрытия / завершения.
Заранее благодарю за любую информацию, которую вы можете дать мне по этой проблеме, с которой я сталкиваюсь.
Мартин
1 ответ
В момент выхода из функции findCityName переменная cityName не изменялась. Обработчик завершения reverseGeocodeLocation в конечном итоге обновит переменную, которая является копией исходного cityName, а не той переменной, которую вы изначально передали в функцию. Обработчики завершения не выполняются сразу: они будут выполняться. Если бы они выполнялись сразу, функции могли бы просто возвращать свои результаты вместо использования обработчиков завершения, верно?
Теперь, я согласен с вами, это странно. Но странно не то, что Swift не обновляет переменную inout. Странно то, что Swift позволяет этой программе компилироваться. Потому что это не имеет смысла. Подписывайтесь на меня:
Представьте себе следующую функцию:
func f() {
var cityName: String = ""
findCityName(location, &cityName)
}
Когда вы вызываете его, переданная вами переменная cityName больше не существует, когда в конечном итоге выполняется обработчик завершения reverseGeocodeLocation. Функция f() давно вышла, а локальная переменная cityName исчезла из существования.
Понял? Бессмысленно даже надеяться, что переменная inout может быть обновлена.
Так. Теперь вы должны рефакторинг вашего кода. Может быть, использовать обработчик завершения.