2015-04-21 108 views
3

我做了一個類函數,其中包含一個閉包,該閉包將位置座標反向地址解析成地址字符串。我最初寫它在一個viewcontroller,但我需要在幾個點運行此代碼。代碼在swift中完成運行之前函數返回

我的問題是,類函數在閉包運行之前返回字符串,所以返回的字符串是空白的。有什麼辦法可以解決這個問題?是否有更好的方法來組織我的代碼而不是使用類函數?

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,因此它將返回字符串,但它是空的,因爲它在異步函數完成之前返回。

相關問題