2016-08-08 3 views
1

Я хочу написать функцию для обратного геокодирования местоположения и присвоить полученную строку переменной. После this поста я получил что-то вроде этого:Невозможная строка возврата из CLGeocoder reverseGeocodeLocation

extension CLLocation { 

    func reverseGeocodeLocation(completion: (answer: String?) -> Void) { 

     CLGeocoder().reverseGeocodeLocation(self) { 

      if let error = $1 { 
       print("[ERROR] \(error.localizedDescription)") 
       return 
      } 

      if let a = $0?.last { 
       guard let streetName = a.thoroughfare, 
        let postal = a.postalCode, 
        let city = a.locality else { return } 

       completion(answer: "[\(streetName), \(postal) \(city)]") 
      } 

     } 
    } 
} 

Для вызова этой функции я только что получил что-то вроде этого:

location.reverseGeocodeLocation { answer in 
    print(answer) 
} 

Но вместо этого я хочу, чтобы присвоить значение строки answer в переменная, и я не знаю, как передать эти данные из закрытия. Каков наилучший способ сделать что-то подобное?

ответ

3

Проблема в том, что он выполняется асинхронно, поэтому вы не можете вернуть значение. Если вы хотите обновить некоторые свойства или переменный, правильное место, чтобы сделать это в замыкании вы предоставляете методу, например:

var geocodeString: String? 

location.reverseGeocodeLocation { answer in 
    geocodeString = answer 
    // and trigger whatever UI or model update you want here 
} 

// but not here 

Всей целью шаблона обработчика закрытия completion является то, что является предпочтительным способ предоставления данных, которые были получены асинхронно.

+0

Вы отправили свои Ответ, пока я сочинял мой. Вы избивали меня за несколько секунд ... :) –

+0

Lol. Сожалею. Возможно, у Stack Overflow должна быть функция, для которой вы знаете, если кто-то сейчас набирает ответ (вроде Skype или некоторых платформ чата) ... – Rob

+0

Спасибо! Решила проблему ✌️ –

1

Короткий ответ: вы не можете. Это не так, как работает асинхронное программирование. Функция reverseGeocodeLocation немедленно возвращается, прежде чем появится ответ. В какой-то момент в будущем результат геокодирования станет доступным, и когда это произойдет, вы вызовете код в своем закрытии. Это когда вы что-то делаете с ответом. Вы можете написать закрытие, чтобы установить ответ в метке, обновить представление таблицы или другое поведение. (Я не помню, вызваны ли вызовы методов геокодирования в основном потоке или фоновом потоке. Если они вызываются в фоновом потоке, вам нужно будет обернуть ваши вызовы пользовательского интерфейса в dispatch_async(dispatch_get_main_queue()).)

+0

FWIW, в отличие от многих асинхронных методов API, с 'reverseGeocodeLocation' вам не нужно беспокоиться о том, чтобы отправлять что-либо в основную очередь. Как говорят [документы] (https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLGeocoder_class/index.html#//apple_ref/occ/instm/CLGeocoder/reverseGeocodeLocation:completionHandler :), " Блок обработчика завершения будет выполнен в основном потоке ». Но ваша точка в главной очереди является отличной, поскольку это вызывает беспокойство многие другие асинхронные методы с обработчиками завершения. – Rob

+1

@Rob, Спасибо, что разъяснил это. Я не помню, как «reverseGeocodeLocation» обработал его закрытие и не успел посмотреть его, когда я отправил свой ответ. –

 Смежные вопросы

  • Нет связанных вопросов^_^