Получить данные CLLocation, используя операцию - PullRequest
0 голосов
/ 11 сентября 2018
import Foundation
import CoreLocation

class LocationOperation: Operation, CLLocationManagerDelegate {

  // MARK: Properties
  private var manager: CLLocationManager?
  private let handler: (CLLocation) -> Void

  // MARK: Initialization
  init(locationHandler: @escaping (CLLocation) -> Void) {
    self.handler = locationHandler
    super.init()
  }

  // MARK: Main
  override func main() {
    DispatchQueue.main.async {
      let manager = CLLocationManager()
      manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
      manager.delegate = self
      manager.startUpdatingLocation()
    }
  }

  override func cancel() {
    DispatchQueue.main.async {
      self.stopLocationUpdates()
      super.cancel()
    }
  }

  private func stopLocationUpdates() {
    manager?.stopUpdatingLocation()
    manager = nil
  }

  // MARK: CLLocationManagerDelegate
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let location = locations.last,
      location.horizontalAccuracy <= manager.desiredAccuracy else {
        return
    }
    stopLocationUpdates()
    handler(location)
  }

  func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    stopLocationUpdates()
    print("Failure to find location") // handle this eventually
    self.cancel()
  }
}

main завершает выполнение до того, как CLLocationManager получит шанс получить местоположение и передать его переданному обработчику.Первой попыткой было переопределить свойство isExecuting и вручную установить для него значение true после вызова обработчика (location) в (_: didUpdateLocations), но это свойство только для чтения.Эта ссылка предоставила способ сделать это, но я не был уверен в реализации. Как остановить остановку операции до того, как она передаст местоположение обработчику? .Спасибо!

1 Ответ

0 голосов
/ 11 сентября 2018

Два серьезных вопроса:

  1. manager объявляется локально в main() и уничтожается после выхода main().

    Заменить

    private var manager: CLLocationManager?
    

    с

    private let manager = CLLocationManager()
    

    и удалить локальную переменную

    let manager = CLLocationManager()

    в main(). Я бы даже предпочел lazy собственность.

  2. Вы должны использовать асинхронный Operation, как описано здесь

...