CLGeocoder всегда возвращает ноль для широты/долготы

Я пытаюсь получить координаты широты/долготы для использования с напоминаниями на основе местоположения (Eventkit). Адрес действителен и правильно отправляется функции, если я укажу необязательный параметр для координат, он возвращается функцией ok, поэтому функция кажется, работает, но геокодер не преобразует адрес, как ожидалось. Я не понимаю, почему этого не произойдет.

var lat: Double?
var lon: Double?

func getLocation(address: String)  -> CLLocation {
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address) { placemarks, error in
        guard let placemark = placemarks?.first else { return }
        
        let coordinate = placemark.location?.coordinate
        lat = coordinate?.latitude //Is always nil
        lon = coordinate?.longitude //Is always nil
        
    }
    // Note: providing ?? sample coordinates in the return below works

    return CLLocation(latitude: lat!, longitude: lon!)
}

if self.locationChoice == "Dog's Home" {
    
    let address = "\(self.dog.addressLine1),\(self.dog.town),\(self.dog.postcode)"
    let structuredLocation = EKStructuredLocation(title: address)
    
    structuredLocation.geoLocation = getLocation(address: address)// asking for CLLocation
    structuredLocation.radius = 500
    let alarm = EKAlarm()
    if self.whenArrivingOrLeaving == 0 {
        alarm.proximity = EKAlarmProximity.enter
    }else {
        alarm.proximity = EKAlarmProximity.leave
    }
    alarm.structuredLocation = structuredLocation
    newReminder.addAlarm(alarm)
}

person My4Paws    schedule 10.10.2020    source источник


Ответы (1)


Это не ноль, вы возвращаете значение из асинхронного метода, вы должны использовать завершение

func getLocation(address: String,completion:@escaping(CLLocation? -> ())) {
     let geocoder = CLGeocoder()
     geocoder.geocodeAddressString(address) { placemarks, error in
           guard let placemark = placemarks?.first else { return } 
           completion(placemark.location)
     }

}

Вызов

getLocation(address: address) { loc in 
   // embed all code here 
}
person Sh_Khan    schedule 10.10.2020
comment
Спасибо, используя print, я вижу, что lat Lon теперь возвращены. Однако я не знаю, как получить результат из того места, где вы ввели весь код, чтобы его можно было использовать? Если я помещу весь код в newReminder.addAlarm(alarm) внутри вызова getLocation, НИКАКОЕ местоположение не будет сохранено в приложении напоминаний. Извините, что не знал этого, я учусь всего несколько месяцев, и мне предстоит пройти долгий путь. :) Если бы вы могли объяснить, как это делается, я думаю, это откроет для меня много новых дверей. - person My4Paws; 10.10.2020
comment
Я пометил ваш ответ как правильный (потому что это так), и мой код работает для разных мест, включая весь код newReminder в вызове getLocation. Это здорово, но приводит к повторяющемуся коду, поэтому, если бы был способ получить только широту и долготу из вызова getLocation (область действия), это избавило бы от дублирования. Но спасибо за вашу помощь. - person My4Paws; 10.10.2020