Ios 当应用程序位于后台时检索当前位置
我已经建立了一个应用程序,你可以按下开始按钮。一旦按下按钮,应用程序将每隔10秒获取一次用户位置,直到按下停止按钮。当我离开应用程序时,或者如果屏幕变黑,在我重新进入应用程序之前,它将不会获得更多的位置 因此,我目前正在尝试在应用程序最小化时更新位置。(我猜它是在后台调用的?),以及当屏幕变黑时。但我的问题是:Ios 当应用程序位于后台时检索当前位置,ios,swift,cllocationmanager,appdelegate,Ios,Swift,Cllocationmanager,Appdelegate,我已经建立了一个应用程序,你可以按下开始按钮。一旦按下按钮,应用程序将每隔10秒获取一次用户位置,直到按下停止按钮。当我离开应用程序时,或者如果屏幕变黑,在我重新进入应用程序之前,它将不会获得更多的位置 因此,我目前正在尝试在应用程序最小化时更新位置。(我猜它是在后台调用的?),以及当屏幕变黑时。但我的问题是: 我是否应该在AppDelegate?中编写此代码,如果是的话。我怎么知道 是否按下了按钮 我应该在AppDelegate中的什么位置添加代码?那怎么可能呢 我是否将位置传回正确的View
如果您知道这些问题的答案,请毫不犹豫地回答。:)我会非常感激的 获取用户在后台位置的最佳方法是根据将此函数放入您的类中使用重大更改位置服务:
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()
扩展位置跟踪器: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()