2015-04-21 3 views
3

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

Моя проблема в том, что функция класса возвращает строку перед запуском закрытия, поэтому возвращаемая строка пуста. Как я могу это исправить? И есть ли лучшие способы организовать мой код, а не использовать функцию класса?

import CoreLocation 
class LocationUtil: CLLocation { 
    class func getLocationAddress(location:CLLocation?) -> NSString { 
     var geocoder = CLGeocoder() 
     var addressString : String = "" 

     if location != nil { 
      geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in 
       var placemark:CLPlacemark! 

       if error == nil && placemarks.count > 0 { 
        placemark = placemarks[0] as CLPlacemark 

        if placemark.subThoroughfare != nil { 
         addressString = placemark.subThoroughfare + " " 
        } 
        if placemark.thoroughfare != nil { 
         addressString = addressString + placemark.thoroughfare + ", " 
        } 
        if placemark.locality != nil { 
         addressString = addressString + placemark.locality + ", " 
        } 
        if placemark.administrativeArea != nil { 
         addressString = addressString + placemark.administrativeArea + " " 
        } 
        if placemark.postalCode != nil { 
         addressString = addressString + placemark.postalCode + " " 
        } 
        if placemark.country != nil { 
         addressString = addressString + placemark.country 
        } 

       } 
       println("Address in closure: \(addressString)") //prints addresss 
      }) 
     } 
     println("Address out of closure: \(addressString)") // doesn't print address 
     return addressString //this returns nothing 
    } 
} 

ответ

9

geocoder.reverseGeocodeLocation работает асинхронно и вызывает completionHandler только после этого завершает.

Таким образом, получение возвращаемого значения, очевидно, не является вариантом. Вместо этого, примите закрытие в качестве входного/аргумента для вашего класса функции

class func getLocationAddress(location: CLLocation, getLocCompletionHandler : (addressString : String?, error : NSError?) -> Void) { 

     geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in 
      //Your current code 
      //... 
      //... 
      println("Address: \(addressString)") 
      //Instead of returning the address string, call the 'getLocCompletionHandler' 
      getLocCompletionHandler(addressString: addressString, error: error) 

     }) 
} 

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

LocationUtil.getLocationAddress(currentLocation, completionHandler: { (addressObject, error) -> Void in 
    println("Address: \(addressString)") 
    //OR handle the error appropriately 
} 

Читайте на closures, чтобы лучше понять концепцию.

Что касается организации кода, функция класса является хорошим выбором в этом случае.

+1

Спасибо, я смог следить за этим и заставить его работать! Все еще работаю через мой ментальный блок, полностью понимая закрытие. –

+0

Забавно, что вы должны сказать, что у вас есть ментальный «блок» для замыканий .. доводчики по существу похожи на «блоки» от ObjC – lukya

4

Вы должны вернуть completionHandler внутри вашего

geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in 

completionHandler будет вызываться, когда функция завершена. Чтобы это сработало, вы также должны сделать свою собственную функцию возвращенной асинхронно.

Это необходимо, потому что ваша функция reverseGeocodeLocation выполняется асинхронно. Ваш основной поток будет продолжать запускать ваш getLocationAddress, поэтому он вернет строку, но она пуста, потому что она возвращается до завершения асинхронной функции.

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