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

问题描述 投票:1回答:2

我已经构建了一个应用程序,您可以按下开始按钮。按下按钮后,应用程序将每隔10秒获取一次用户位置,直到按下停止按钮。当我离开应用程序或屏幕变黑时,在重新进入应用程序之前,它将不再获得任何位置。

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

  1. 我应该在AppDelegate中编写这段代码吗?如果是的话。如何知道按钮是否被按下?
  2. 我应该在AppDelegate中添加代码吗?我怎样才能将位置传递回正确的ViewController? (因为我不能为AppDelegate的segue做任何准备)

如果您知道这些问题的答案,请随时回答。 :) 我真的很感激!

ios swift cllocationmanager appdelegate
2个回答
1
投票

在后台获取用户位置的最佳方法是根据apple's documentation使用重要更改位置服务将此功能放入您的班级:

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(_ manager:CLLocationManager,didUpdateLocations locations:[CLLocation]),所以你可以根据那里的位置做你想做的事情。

请记住要求使用位置的权限并停止使用locationManager.stopMonitoringSignificantLocationChanges()进行跟踪


0
投票
  1. 获取始终允许的位置权限
  2. 从上面的方式设置allowBackgroundLocationUpdates的位置管理器,你可以获得位置,在每个位置更改存储此信息并将其发送到服务器。下面是示例代码 typealias LocateMeCallback =(_ location:CLLocation?) - > Void /* 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()
© www.soinside.com 2019 - 2024. All rights reserved.