为什么这个 Singleton Location Manager class 返回一个 nil Location?

Why is this Singleton Location Manager class returning a nil Location?

我正在尝试在我的项目中使用此 blog 中的 LocationSingleton Class。我喜欢它的简单用法。

您只需调用即可开始更新位置:

LocationSingleton.sharedInstance.startUpdatingLocation()

只需调用即可获取最后位置:

LocationSingleton.sharedInstance.lastLocation

我的目的是启动定位服务,获取最后一个位置,这样我就可以使用返回的位置从 Firebase 获取用户。

问题是如果我在 startUpdatingLocation 之后直接调用 lastLocation 它 returns 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()
    }

}

位置管理器异步工作并提供委托方法来获取结果。

在您的 class 中采用 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()
}

检测到位置时,将调用委托方法之一