I'm rather new at swift and have been doing some research on how to answer this question myself since I want to learn, but I am completely stumped.
I have a function which requests data from a server, and after the data is received, a completion handler is executed which parses the data. Within the previously mentioned completion handler, another function is called which is passed a completion handler itself.
For some reason, the function call within the function is being being skipped, and being finished after the first completion handler is fully executed. This might make more sense with the code below:
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)
    }
}
I added those print statements which print "YOOO" and "HEYYY" just so I could see what was being executed first, and "HEYY" is always first. I just need to make sure that the geocoding always happens before the object is persisted. I saw a stackoverflow post which mentioned objc_sync_enter(self) for synchronous operation, but im not even sure if it's what I need.
This is the function which geocodes the site (incase it helps):
    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)
        }
    })
}
 
     
    