Ios 当应用程序位于后台时检索当前位置

Ios 当应用程序位于后台时检索当前位置,ios,swift,cllocationmanager,appdelegate,Ios,Swift,Cllocationmanager,Appdelegate,我已经建立了一个应用程序,你可以按下开始按钮。一旦按下按钮,应用程序将每隔10秒获取一次用户位置,直到按下停止按钮。当我离开应用程序时,或者如果屏幕变黑,在我重新进入应用程序之前,它将不会获得更多的位置 因此,我目前正在尝试在应用程序最小化时更新位置。(我猜它是在后台调用的?),以及当屏幕变黑时。但我的问题是: 我是否应该在AppDelegate?中编写此代码,如果是的话。我怎么知道 是否按下了按钮 我应该在AppDelegate中的什么位置添加代码?那怎么可能呢 我是否将位置传回正确的View

我已经建立了一个应用程序,你可以按下开始按钮。一旦按下按钮,应用程序将每隔10秒获取一次用户位置,直到按下停止按钮。当我离开应用程序时,或者如果屏幕变黑,在我重新进入应用程序之前,它将不会获得更多的位置

因此,我目前正在尝试在应用程序最小化时更新位置。(我猜它是在后台调用的?),以及当屏幕变黑时。但我的问题是:

  • 我是否应该在AppDelegate?中编写此代码,如果是的话。我怎么知道 是否按下了按钮
  • 我应该在AppDelegate中的什么位置添加代码?那怎么可能呢 我是否将位置传回正确的ViewController?(自从我 无法从AppDelegate为segue做任何准备)

  • 如果您知道这些问题的答案,请毫不犹豫地回答。:)我会非常感激的

    获取用户在后台位置的最佳方法是根据将此函数放入您的类中使用重大更改位置服务:

    func startReceivingSignificantLocationChanges() {
        let authorizationStatus = CLLocationManager.authorizationStatus()
        if authorizationStatus != .authorizedAlways {
        // User has not authorized access to location information.
            return
        } 
    
        if !CLLocationManager.significantLocationChangeMonitoringAvailable() {
        // The service is not available.
            return
        }
        locationManager.delegate = self
        locationManager.startMonitoringSignificantLocationChanges()
    }
    
    还有这个函数:

    func locationManager(_ manager: CLLocationManager,  didUpdateLocations 
        locations: [CLLocation]) {
           let lastLocation = locations.last!
               
           // Do something with the location. 
    }
    
    因此,您只需在按钮内调用startReceivingSignificantLocationChanges(),它将调用locationManager(uManager:CLLocationManager,didUpdateLocations locations:[CLLocation]),因此您可以对该位置执行所需操作

    请记住使用location Manager请求使用location并停止跟踪的权限。停止监视重要location Changes()

  • 获取始终允许的位置权限
  • 将allowsBackgroundLocationUpdates的位置管理器设置为true 通过以上方法,您可以在每次位置更改中获取位置存储此信息并将其发送到服务器。下面是示例代码

    typealias LocateMeCallback=(\uLocation:CLLocation?)->Void

    }

    扩展位置跟踪器:CLLocationManagerDelegate{
    func locationManager(manager:CLLocationManager,didUpdateLocations位置:[CLLocation]){
    打印(位置)
    guard let location=locations.first-else{return}
    guard-location.timestamp.TimeIntervalencesEnow<120,//仅验证最近获取的位置
    location.HorizontalAccurance>0,//验证水平精度-Ve表示无效
    位置。水平精度<200//验证水平精度>100 M
    否则{
    打印(“接收到无效位置或忽略旧的(缓存的)更新”)
    返回
    }
    self.locations.append(位置)
    lastLocation=位置
    如果让activeRide=RideManager.shared.activeRide,
    让u=AccessTokenHelper.shared.accessToken,
    让activeRideId=activeRide.ride\u id,
    让type=activeRide.ridestatustype可选,
    类型==。已启动{
    //启动后特定行驶的存储位置
    LocationUpdater.shared.saveInDataBase(rideId:activeRideId,位置:[位置])
    }
    }
    func locationManager(manager:CLLocationManager,didFailWithError:error){
    打印(错误。本地化描述)
    }
    func locationManager(\ manager:CLLocationManager,didChangeAuthorization状态:CLAuthorizationStatus){
    enableLocationServices()
    }
    }
    /*
    此类负责在n秒后更新服务器上的位置,并在n秒后更新路径。
    **/
    类位置计时器{
    静态let时间:双精度=30
    }
    /*
    类在第n秒后将位置更新到服务器
    **/
    类LocationUpdater:NSObject{
    静态let shared=LocationUpdater(n:Double(LocationTimer.time),tracker:LocationTracker.shared)
    让n:加倍
    私人出租跟踪器:LocationTracker
    变量计时器:计时器!=nil
    初始化(n:Double,tracker:LocationTracker){
    self.n=n
    self.tracker=跟踪器
    super.init()
    }
    func startUpdater(){
    self.timer?.invalidate()
    self.timer=nil
    self.timer=timer.scheduledTimer(时间间隔:n,目标:self,选择器:#选择器(updateLocationsToServer),用户信息:nil,重复:true)
    self.timer.fire()
    }
    func stopUpdater(){
    self.timer?.invalidate()
    self.timer=nil
    }
    @objc func updateLocationsToServer(){
    //更新到服务器
    }
    }
    //用法
    LocationTracker.shared.startTracking()
    LocationUpdater.shared.startUpdater()文件
    

  • 当用户正在使用其他应用程序时,您是否获得了用户使用位置服务的权限?@RamyMohamed我不确定该权限。但我已经在“后台模式”中激活了“位置更新”,我还在信息列表中设置了两个权限:*位置始终和*使用时的位置查看此博客:因此,当应用程序处于后台时,您希望定期(比如每10秒)更新位置。要实现这一点,您需要运行计时器以定期获取位置。但当应用程序处于后台时,无法运行计时器。一旦应用程序进入BG,它将很快被暂停。当应用程序位于BG中时,您可以使用重要位置服务或地理围栏服务来更新位置。即使在应用程序终止时,这两项服务也会起作用。SLC和Geo Fenging也有自己的警告,如准确性不正确、无法配置间隔等。一旦你看完这篇文章,你会了解更多:,非常有趣!所以我不需要调用应用程序代理中的任何内容?根据你的第一个片段。我不应该在括号内做任何事情://User has not authorized access to location information&//服务不可用。?好的,代码已添加到我的应用程序中。只有一个问题:我如何在大约10秒后自动更新它?还是几米后?我是说,我需要经常更新。我希望你能理解我,谢谢我不需要在a区打电话
    /*
     LocationTracker to track the user in while navigating from one place to other and store new locations in locations array.
     **/
    class LocationTracker: NSObject {
    
    static let shared = LocationTracker()
    
    var lastLocation: CLLocation?
    var locations: [CLLocation] = []
    
    var previousLocation: CLLocation?
    var isPreviousIsSameAsCurrent: Bool {
        if let previous = previousLocation, let last = lastLocation {
           return previous == last
        }
        return false
    }
    var isAggressiveModeOn = false
    var locationManager: CLLocationManager = {
       let locationManager = CLLocationManager()
       locationManager.allowsBackgroundLocationUpdates = true
       locationManager.pausesLocationUpdatesAutomatically = true
       locationManager.activityType = .automotiveNavigation
       return locationManager
    }()
    
    var locateMeCallback: LocateMeCallback?
    
    var isCurrentLocationAvailable: Bool {
        if lastLocation != nil {
          return true
        }
        return false
    }
    
    func enableLocationServices() {
        locationManager.delegate = self
        switch CLLocationManager.authorizationStatus() {
        case .notDetermined:
            // Request when-in-use authorization initially
            locationManager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            // Disable location features
            print("Fail permission to get current location of user")
        case .authorizedWhenInUse:
            // Enable basic location features
            enableMyWhenInUseFeatures()
       case .authorizedAlways:
            // Enable any of your app's location features
            enableMyAlwaysFeatures()
       }
    }
    
    func enableMyWhenInUseFeatures() {
       locationManager.startUpdatingLocation()
       locationManager.delegate = self
       escalateLocationServiceAuthorization()
    }
    
    func escalateLocationServiceAuthorization() {
        // Escalate only when the authorization is set to when-in-use
        if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
            locationManager.requestAlwaysAuthorization()
        }
    }
    
    func enableMyAlwaysFeatures() {
       enableCoarseLocationFetch()
       locationManager.startUpdatingLocation()
       locationManager.delegate = self
    }
    
    // Enable Rough Location Fetch
    func enableCoarseLocationFetch() {
       isAggressiveModeOn = false
       locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
       locationManager.distanceFilter = 100
    
    }
    
    // Enable Aggressive Location Fetch
    func enableAggressiveLocationFetch() {
        isAggressiveModeOn = true
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.distanceFilter = 10
    
    }
    
    func locateMe(callback: @escaping LocateMeCallback) {
        self.locateMeCallback = callback
        if lastLocation == nil {
            enableLocationServices()
        } else {
           callback(lastLocation)
        }
    }
    
    func startTracking() {
         enableLocationServices()
    }
    
    func stopTracking() {
        locationManager.stopUpdatingLocation()
    }
    
    func resetPreviousLocation() {
        previousLocation = nil
    }
    
    private override init() {}
    
    extension LocationTracker: CLLocationManagerDelegate {
    
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    
    
            print(locations)
            guard let location = locations.first else { return }
            guard -location.timestamp.timeIntervalSinceNow < 120, // Validate only location fetched recently
                location.horizontalAccuracy > 0, // Validate Horizontal Accuracy - Ve means Invalid
                location.horizontalAccuracy < 200 // Validate Horizontal Accuracy > 100 M
                else {
                print("invalid location received OR ignore old (cached) updates")
                return
            }
    
            self.locations.append(location)
            lastLocation = location
    
    
            if let activeRide = RideManager.shared.activeRide,
                let _ = AccessTokenHelper.shared.accessToken,
                let activeRideId = activeRide.ride_id,
                let type = activeRide.rideStatusTypeOptional,
                type == .started  {
                //Store Location For A particular Ride after Start
                LocationUpdater.shared.saveInDataBase(rideId: activeRideId, locations: [location])
            }
    
        }
    
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print(error.localizedDescription)
        }
    
        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
            enableLocationServices()
        }
    
    }
    
    
    /*
     This class having responsibility of Updating the location on server after n second and update path after n second.
     **/
    class LocationTimer {
        static let time: Double = 30
    }
    
    /*
      class to update locations to server after nth second
     **/
    class LocationUpdater: NSObject {
    
        static let shared = LocationUpdater(n: Double(LocationTimer.time), tracker: LocationTracker.shared)
    
        let n: Double
        private let tracker: LocationTracker
        var timer: Timer! = nil
    
        init(n: Double, tracker: LocationTracker) {
            self.n = n
            self.tracker = tracker
            super.init()
        }
    
        func startUpdater() {
            self.timer?.invalidate()
            self.timer = nil
            self.timer = Timer.scheduledTimer(timeInterval: n, target: self, selector: #selector(updateLocationsToServer), userInfo: nil, repeats: true)
            self.timer.fire()
        }
    
        func stopUpdater() {
            self.timer?.invalidate()
            self.timer = nil
        }
    
        @objc func updateLocationsToServer() {
    // update to server
     }
    }
    
    
    // usage 
    LocationTracker.shared.startTracking()
    LocationUpdater.shared.startUpdater()