0

I have written the following function to find out the placemark of an image. This also works, because if a url of an image with the appropriate metadata is given the correct placemark is returned.

func GetLocationFromFoto(url: URL, completion: @escaping ([CLPlacemark]?) -> Void) {
    guard let con = getImageMetadata(imageURL: url)?["{GPS}"] as? NSDictionary else {
        completion(nil)
        return
    }
    
    if let lat = con["Latitude"] as? CLLocationDegrees, let lon = con["Longitude"] as? CLLocationDegrees {
        let loc = CLLocation(latitude: lat, longitude: lon)
        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(loc) { placemarks, error in
            if let error = error {
                print("Geocoding error: \(error.localizedDescription)")
                completion(nil)
                return
            }
            let country = placemarks
            completion(country)
        }
    } else {
        completion(nil)
    }
}

Since the function geocoder.reverseGeocodeLocation(loc) runs async, I used a completion. But now it disturbs the further flow of the program. So is there a possibility that the main function waits for this async function and then has a simple return value? The head of the function should look like this: func GetLocationFromFoto(url: URL) -> [CLPlacemark]? {

Thank you very much in advance!

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
Theo
  • 3
  • 1
  • Are you aware of Swift's Concurrency features? i.e. `async` and `await`. Your function could be `func GetLocationFromFoto(url: URL) async throws -> [CLPlacemark]`. – Sweeper Aug 07 '23 at 03:49

1 Answers1

0

I used this link to getting the latitude and longitude Core Location to an iOS Framework. As per your justification you need to wait for the geocoding function then you want to execute your code. So, I just simply print the "Hello" and the "World" separately so first "Hello" prints and then it waits for the function to complete and then it prints "World".

import Foundation
import CoreLocation

class LocationReporter: NSObject, CLLocationManagerDelegate {

    static let sharedInstance = LocationReporter()

    func startUpdating(locationManager: CLLocationManager) {
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.startUpdatingLocation()
    }

    func stopUpdating(locationManager: CLLocationManager) {
        locationManager.stopUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.first {
            let lati = location.coordinate.latitude
            let longi = location.coordinate.longitude
            
            print("latitude: ", location.coordinate.latitude)
            print("longitude: ", location.coordinate.longitude)
            Task {
                print("Hello")
                await GetLocationFromFoto(latitude:lati, longitude:longi)
                print("World")
            }
        }
    }
    
    func GetLocationFromFoto(latitude: CLLocationDegrees, longitude: CLLocationDegrees) async {
        let lat = latitude
        let lon = longitude
        let loc = CLLocation(latitude: lat, longitude: lon)
        let geocoder = CLGeocoder()
        do {
            let country = try await geocoder.reverseGeocodeLocation(loc)
            for data in country {
                print(data.country)
            }
        } catch let error {
            print("Geocoding error: \(error.localizedDescription)")
        }
    }
}