Swift создает класс с помощью делегата

#swift #core-location

#swift #расположение ядра

Вопрос:

Об этом где-то можно было бы поговорить, но я не могу найти ни одной статьи, в которой говорится об этом. Я пытаюсь написать класс, который использует собственный API CoreLocation от Apple. Моя цель — иметь возможность вызывать что-то вроде LocationTrack.getDPS и возвращать координаты gps из делегата LocationManager.

 class LocationTrack: CLLocationManagerDelegate  {

    if (CLLocationManager.locationServicesEnabled())
            {
                locationManager = CLLocationManager()
                locationManager.delegate = self
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                locationManager.requestAlwaysAuthorization()
                locationManager.startUpdatingLocation()
            }
        }

  func getDPS(completion: @escaping (result: [CLLocation]) -> () {

       //How to get below delegate response into this function?

    }

  func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

      print(locations)

}


    }
  

Комментарии:

1. Почему бы вам не создать свойство для CLLocationManager?

Ответ №1:

Определите свойство для захвата вашего обработчика завершения:

 private var handler: (([CLLocation]) -> Void)?
  

И getDPS сохраните его и начните обновлять местоположения:

 func getDPS(_ completion: @escaping ([CLLocation]) -> Void) {
    handler = completion
    locationManager.startUpdatingLocation()
}
  

И тогда ваш didUpdateLocations может вызвать это закрытие:

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    handler?(locations)
    handler = nil
    locationManager.stopUpdatingLocation()
}
  

Собирая все это вместе, может быть, что-то вроде:

 class LocationTrack: NSObject {
    private lazy var locationManager: CLLocationManager = {
        let locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()   // perhaps `requestWhenInUseAuthorization` is better?
        return locationManager
    }()

    private var handler: (([CLLocation]) -> Void)?

    func getDPS(_ completion: @escaping ([CLLocation]) -> Void) {
        handler = completion
        locationManager.startUpdatingLocation()
    }
}

extension LocationTrack: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        handler?(locations)
        handler = nil
        locationManager.stopUpdatingLocation()
    }
}
  

Очевидно, что вы можете добавить свою собственную обработку ошибок и все, что у вас есть, но, надеюсь, это иллюстрирует идею сохранения закрытия в свойстве и вызова его при получении обратного вызова делегата.

Комментарии:

1. Это здорово. Можете ли вы объяснить необходимость NSObject определения класса in и определения locationManager as lazy ?

2. @Nick — I подкласс, NSObject потому что CLLocationManager это Objective-C, где все объекты являются NSObject подклассами. delegate Из CLLocationManager должен быть NSObject подкласс. Попробуйте удалить NSObject наследование, и вы получите предупреждение компилятора, в котором он пытается установить себя в качестве delegate . Что касается lazy , я делаю это, потому что хочу использовать замыкание для инициализации locationManager (сохраняет код красивым и аккуратным), но я не могу ссылаться self на закрытие, если оно не является ленивым (т. Е. Создается позже при первом обращении, а не при LocationTrack первом создании экземпляра).