2016-03-23 35 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

太棒了,感谢您的编辑。这是我需要的解决方案。 –

相关问题