Почему этот класс Singleton Location Manager возвращает нулевое местоположение? - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь использовать ниже LocationSingleton Class из этого блога в моем проекте.Мне нравится простота его использования.

Вы начинаете обновлять местоположение, просто позвонив:

LocationSingleton.sharedInstance.startUpdatingLocation()

Получить последнее местоположение, просто позвонив:

LocationSingleton.sharedInstance.lastLocation

Мое намерениечтобы запустить службы определения местоположения, получить последнее местоположение, чтобы я мог затем выбрать пользователей из Firebase, используя возвращенное местоположение.

Проблема в том, что если я позвоню lastLocation сразу после startUpdatingLocation, он вернет nil.

После некоторой отладки я обнаружил, что причина в том, что службы определения местоположения на устройстве запускаются медленно, и поэтому, когда вызывается lastLocation, устройства еще не получили местоположение. Я хотел бы выполнить следующую команду, как только будет записано lastLocation.Как мне этого добиться?

Я хотел бы понять, как используется Protocol?

import UIKit
import CoreLocation

protocol LocationServiceDelegate {
    func locationDidUpdateToLocation(currentLocation: CLLocation)
    func locationUpdateDidFailWithError(error: NSError)
}

class LocationSingleton: NSObject,CLLocationManagerDelegate {
    var locationManager: CLLocationManager?
    var lastLocation: CLLocation?
    var delegate: LocationServiceDelegate?

    static let sharedInstance:LocationSingleton = {
        let instance = LocationSingleton()
        return instance
    }()

    override init() {
        super.init()
        self.locationManager = CLLocationManager()

        guard let locationManagers=self.locationManager else {
            return
        }

        if CLLocationManager.authorizationStatus() == .notDetermined {
            //locationManagers.requestAlwaysAuthorization()
            locationManagers.requestWhenInUseAuthorization()
        }

        if #available(iOS 9.0, *) {
            //            locationManagers.allowsBackgroundLocationUpdates = true
        } else {
            // Fallback on earlier versions
        }
        locationManagers.desiredAccuracy = kCLLocationAccuracyBest
        locationManagers.pausesLocationUpdatesAutomatically = false
        locationManagers.distanceFilter = 0.1
        locationManagers.delegate = self

    }


    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else {
            return
        }
        self.lastLocation = location
        updateLocation(currentLocation: location)

    }

    @nonobjc func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            locationManager?.requestWhenInUseAuthorization()
            break
        case .authorizedWhenInUse:
            locationManager?.startUpdatingLocation()
            break
        case .authorizedAlways:
            locationManager?.startUpdatingLocation()
            break
        case .restricted:
            // restricted by e.g. parental controls. User can't enable Location Services
            break
        case .denied:
            // user denied your app access to Location Services, but can grant access from Settings.app
            break
        default:
            break
        }
    }



    // Private function
    private func updateLocation(currentLocation: CLLocation){

        guard let delegate = self.delegate else {
            return
        }

        delegate.locationDidUpdateToLocation(currentLocation: currentLocation)
    }

    private func updateLocationDidFailWithError(error: NSError) {

        guard let delegate = self.delegate else {
            return
        }

        delegate.locationUpdateDidFailWithError(error: error)
    }

    func startUpdatingLocation() {
        print("Starting Location Updates")
        self.locationManager?.startUpdatingLocation()
        //        self.locationManager?.startMonitoringSignificantLocationChanges()
    }

    func stopUpdatingLocation() {
        print("Stop Location Updates")
        self.locationManager?.stopUpdatingLocation()
    }

    func startMonitoringSignificantLocationChanges() {
        self.locationManager?.startMonitoringSignificantLocationChanges()
    }

}

1 Ответ

0 голосов
/ 04 июня 2018

Менеджер местоположений работает асинхронно и предоставляет методы делегата для получения результата.

В вашем классе используйте LocationServiceDelegate, реализуйте методы делегата и задайте делегат, например, в viewDidLoad

func locationDidUpdateToLocation(currentLocation: CLLocation)
{
    print(LocationSingleton.sharedInstance.lastLocation)
}

func locationUpdateDidFailWithError(error: NSError)
{
    print(error)
}

func viewDidLoad()
    super viewDidLoad()

    let locationSingleton = LocationSingleton.sharedInstance
    locationSingleton.delegate = self
    locationSingleton.startUpdatingLocation()
}

При обнаружении местоположения один из методов делегата называется

...