iOS 定位服务在后台以较小的间隔或距离发生

Posted

技术标签:

【中文标题】iOS 定位服务在后台以较小的间隔或距离发生【英文标题】:iOS location services in the background to occur at smaller intervals or distances 【发布时间】:2017-07-04 10:09:05 【问题描述】:

以下代码是我为 swift 3.0.2 更新的应用程序委托文件

import UIKit
import CoreLocation



@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate 

var window: UIWindow?
var locationManager: CLLocationManager?
var significatLocationManager : CLLocationManager?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
    if(UIApplication.shared.backgroundRefreshStatus == UIBackgroundRefreshStatus.available)
        print("yes")
    else
        print("no")
    

    if launchOptions != nil


        let remoteNotif = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary

        if remoteNotif != nil 
            self.significatLocationManager = CLLocationManager()
            self.significatLocationManager?.delegate = self
            self.significatLocationManager?.requestAlwaysAuthorization()
            if #available(ios 9.0, *) 
                self.significatLocationManager!.allowsBackgroundLocationUpdates = true
            
            self.significatLocationManager?.startMonitoringSignificantLocationChanges()

        else

            self.locationManager           = CLLocationManager()
            self.locationManager?.delegate = self
            self.locationManager?.requestAlwaysAuthorization()
            if #available(iOS 9.0, *) 
                self.locationManager!.allowsBackgroundLocationUpdates = true
            

            self.locationManager?.startMonitoringSignificantLocationChanges()
        

    else

        self.locationManager           = CLLocationManager()
        self.locationManager?.delegate = self
        self.locationManager?.requestAlwaysAuthorization()
        if #available(iOS 9.0, *) 
            self.locationManager!.allowsBackgroundLocationUpdates = true
        

        self.locationManager?.startMonitoringSignificantLocationChanges()

    

    return true




func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])

    //let locationArray = locations as NSArray
    //let locationObj = locationArray.lastObject as! CLLocation
    //let coord = locationObj.coordinate


    let currentLocation = locations.last!
    //print("Current location: \(currentLocation)")
    print("delegate longitude: \(currentLocation.coordinate.longitude)")
    print("delegate latitude: \(currentLocation.coordinate.latitude)")

    let t_longtitude = String(currentLocation.coordinate.longitude)
    let t_latitude = String(currentLocation.coordinate.latitude)
    let longtitude:Double = currentLocation.coordinate.longitude as Double
    let latitude:Double = currentLocation.coordinate.latitude as Double
    let svd_longtitude:Double = (UserDefaults.standard.object(forKey: "longtitude") as? Double)!
    let svd_latitude:Double = (UserDefaults.standard.object(forKey: "latitude") as? Double)!
    let coordinate1 = CLLocation(latitude: latitude, longitude: longtitude)
    let coordinate2 = CLLocation(latitude: svd_latitude, longitude: svd_longtitude)
    let distanceInMeters = coordinate1.distance(from: coordinate2) // result is in meters
    print("distanceInMeters: \(distanceInMeters)")
    UserDefaults.standard.set(latitude, forKey: "latitude")
    UserDefaults.standard.set(longtitude, forKey: "longtitude")
    UserDefaults.standard.synchronize()
    let device_id = UIDevice.current.identifierForVendor!.uuidString
    let status = update_device(longtitude: t_longtitude, latitude: t_latitude, device_id: device_id)
    print("status: \(status)")



func applicationDidEnterBackground(_ application: UIApplication) 

    if self.significatLocationManager != nil 

        self.significatLocationManager?.startMonitoringSignificantLocationChanges()
    else

        self.locationManager?.startMonitoringSignificantLocationChanges()
    




func update_device(longtitude: String, latitude:String, device_id:String) -> Int 

    print("update device")

    let deviceID = UIDevice.current.identifierForVendor!.uuidString
    var status:Int = 0

    var request = URLRequest(url: URL(string: "https://someurl")!)

    request.httpMethod = "POST"

    let postString = "device_id=\(deviceID)&longtitude=\(longtitude)&latitude=\(latitude)"

    request.httpBody = postString.data(using: .utf8)
    let task = URLSession.shared.dataTask(with: request)  data, response, error in
        guard let data = data, error == nil else                                                  // check for fundamental networking error
            print("error=\(String(describing: error))")
            return
        

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200            // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        

        let responseString:String = (String(data: data, encoding: .utf8))!
        print("responseString = \(String(describing: responseString))")

        let dict = self.convertToDictionary(text: responseString)

        //UserDefaults.standard.set(dict, forKey: "myUserDetails")
        //UserDefaults.standard.synchronize()
        //self.activityIndicator.stopAnimating()

        //let status:Int = dict?["status"] as! Int
        print("status: \(status)")
        status = dict?["status"] as! Int

    

    task.resume()
    return status





func convertToDictionary(text: String) -> [String: Any]? 
    if let data = text.data(using: .utf8) 
        do 
            return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
         catch 
            print(error.localizedDescription)
        
    
       return nil
   


  

我一直要求允许,更新 info.plist 与

<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to your location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to your location</string>
<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

代码有效并且我的数据库正在被填满,但是当应用程序在后台时,didUpdateLocations 被触发到远离一个位置。当旧位置和新位置之间的变化小于 200 米时,我该怎么做才能让应用调用 didUpdateLocations

谢谢

【问题讨论】:

【参考方案1】:

您可以像这样设置 100 米的位置,如果位置更改为距离当前位置 100 米,它会更新您

_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

【讨论】:

当您初始化 CLLocationManager 并将您的委托设置在您使用此代码的位置时。

以上是关于iOS 定位服务在后台以较小的间隔或距离发生的主要内容,如果未能解决你的问题,请参考以下文章

当两个ID在Scala中具有相同的最高价格时,以较小的ID获得最高价格

需要完整的图像作为背景Cover Scroll,当前Cover看起来已放大。我希望以较小的缩放而不是完整的缩放显示实际图像

如何避免循环内的数据丢失

使用自动布局和 SnapKit 进行相对定位

较小的 MapKit 缩放间隔 iPhone

在任何时间点在 iOS7 或更高版本中在后台启动定位服务