2016-03-23 39 views
0

我在swift上很新,並且一直在做一些關於如何自己回答這個問題的研究,因爲我想學習,但我完全難住。即使在完成處理程序中異步執行的Swift代碼

我有一個從服務器請求數據的函數,並且在收到數據之後,會執行一個完成處理程序來解析數據。在前面提到的完成處理程序中,調用了另一個函數,它本身傳遞了一個完成處理程序。

出於某種原因,該函數中的函數調用正在被跳過,並且在第一個完成處理程序完全執行後完成。這可能更有意義與下面的代碼:

func loadSites(forceDownload: Bool){ 
    self.inspectionSites = MyData.getLocallyStoredInspectionSites() 
    if self.inspectionSites.count < 1 || forceDownload { 

     self.http.requestSites({(sitesAcquired, jsonObject) -> Void in 
      guard sitesAcquired else{ 
       SwiftOverlays.removeAllBlockingOverlays() 
       MyAlertController.alert("Unable to acquire sites from server or locally") 
       return 
      } 
      let result = jsonObject 

      for (_,subJson):(String, JSON) in result!.dictionaryValue { 
       let site = InspectionSite() 
       site.name = subJson[self.currentIndex]["name"].string! 
       site.city = subJson[self.currentIndex]["city"].string! 
       site.address = subJson[self.currentIndex]["address"].string! 
       site.state = subJson[self.currentIndex]["state"].string! 
       site.zip = subJson[self.currentIndex]["zip"].stringValue 
       site.siteId = subJson[self.currentIndex]["id"].string! 

       objc_sync_enter(self) //SAW A STACKOVERFLOW POST WITH THIS, THOUGHT IT MIGHT HELP 
       MyLocation.geoCodeSite(site, callback:{(coordinates) -> Void in 
        print("YO!!!! GEOCODING SITE!") 
        self.localLat = coordinates["lat"]! 
        self.localLon = coordinates["lon"]! 
       }) 
       objc_sync_exit(self) 

       for type in subJson[self.currentIndex]["inspection_types"]{ 
        let newType = InspectionType() 
        newType.name = type.1["name"].string! 
        newType.id = type.1["id"].string! 
        site.inspectionTypes.append(newType) 
       } 



       site.lat = self.localLat 
       print("HEYY!!!! ASSIGNING COORDS") 
       site.lon = self.localLon 
       let address = "\(site.address), \(site.city), \(site.state) \(site.zip)" 
       site.title = site.name 
       site.subtitle = address 
       MyData.persistInspectionSite(site) 
       self.currentIndex++ 
      } 

      self.inspectionSites = MyData.getLocallyStoredInspectionSites() 
      SwiftOverlays.removeAllBlockingOverlays() 
      self.showSitesOnMap(self.proteanMap) 
     }) 


    }else{ 
     SwiftOverlays.removeAllBlockingOverlays() 
     self.showSitesOnMap(self.proteanMap) 
    } 


} 

我添加了打印「YOOO」和「HEYYY」只是這樣我就可以看到什麼是首先被執行的那些打印語句和「HEYY」永遠是第一位。我只需要確保地理編碼總是在對象被持久化之前發生。我看到一個提到objc_sync_enter(self)進行同步操作的stackoverflow文章,但我甚至不知道它是否是我需要的。

這是地理編碼的網站(櫃面它幫助)功能:

class func geoCodeSite(site: InspectionSite, callback: ((coordinates: Dictionary<String, String>)->Void)?) { 
    let geocoder = CLGeocoder() 

    let address: String = "\(site.address), \(site.city), \(site.state) \(site.zip)" 
    print(address) 
    geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in 
     if((error) != nil){ 
      print("Error", error) 
     } 
     if let placemark = placemarks?.first { 
      MyLocation.mLat = String(stringInterpolationSegment:placemark.location!.coordinate.latitude) 
      MyLocation.mLon = String(stringInterpolationSegment:placemark.location!.coordinate.longitude) 
      MyLocation.coordinates = ["lat":mLat, "lon":mLon] 
      print(MyLocation.coordinates) 
      callback?(coordinates: MyLocation.coordinates) 
     } 
    }) 
} 

回答

1

我覺得你的眼看預期的行爲。你有異步方法兩個層面:

requestSites 
    geoCodeSite 

由於geoCodeSite方法也是異步的,其callback是行之後很好的執行:

MyData.persistInspectionSite(site) 

所以你的問題是如何等到所有InspectionSite在堅持網站之前進行了地理編碼,對吧?

調度組可用於檢測多個異步事件何時完成,請參閱我的回答here

如何實現調度組

dispatch_groups用來觸發一個回調,當多個異步回調已經完成。在你的情況下,你需要等待所有geoCodeSite異步回調才能完成,然後再堅持你的網站。

因此,創建一個調度組,發起您的geoCodeSite調用,並實施調度回調,您可以在其中保留您的地理編碼網站。

var myGroup = dispatch_group_create() 
dispatch_group_enter(myGroup) 
... 
fire off your geoCodeSite async callbacks 
... 
dispatch_group_notify(myGroup, dispatch_get_main_queue(), { 
    // all sites are now geocoded, we can now persist site 
}) 

不要忘記添加

dispatch_group_leave(myGroup) 

geoCodeSite的閉包內!否則,dispatch_group將永遠不會知道您的異步呼叫何時完成。

+0

嗯,所以即時通訊審查你的其他答案,即時通訊試圖實現你有什麼到我的功能。如果你有第二個問題,你可以指點一下我的方向嗎? –

+0

太棒了,感謝您的編輯。這是我需要的解決方案。 –

相關問題