Ios 设备上不会触发重大位置更改

Ios 设备上不会触发重大位置更改,ios,core-location,cllocationmanager,Ios,Core Location,Cllocationmanager,我正在使用重要的位置变化监控。当我在模拟器中运行代码并选中高速公路选项时,我会定期更新位置。我抓取这些更新并将它们保存在NSUserDefaults中,然后每隔10秒更新一次tableview,以便查看是否有任何更新。如果我在真实设备上运行该应用程序,则不会得到任何更新。我把手机放在口袋里,走了80多公里,去过两个城市。零更新。不确定我是否把事情搞砸了。我正在附上密码。代码是复制粘贴的,可以随意测试。只需确保在故事板中使用TableViewController并将单元格id设置为id。我缺少什么

我正在使用重要的位置变化监控。当我在模拟器中运行代码并选中高速公路选项时,我会定期更新位置。我抓取这些更新并将它们保存在NSUserDefaults中,然后每隔10秒更新一次tableview,以便查看是否有任何更新。如果我在真实设备上运行该应用程序,则不会得到任何更新。我把手机放在口袋里,走了80多公里,去过两个城市。零更新。不确定我是否把事情搞砸了。我正在附上密码。代码是复制粘贴的,可以随意测试。只需确保在故事板中使用TableViewController并将单元格id设置为id。我缺少什么?我正在测试iphone5

info.plist:

编辑:在apple docs中找到。是否应以不同方式创建我的
locationManager

由于位置更新而重新启动应用程序时,启动 选项字典已传递给您的 应用程序:将使用选项完成启动:或 application:didFinishLaunchingWithOptions:方法包含 UIApplicationLaunchActionSlocationKey键。钥匙的存在 表示新位置数据正在等待发送到应用程序。 要获取该数据,必须创建新的CLLocationManager对象 并重新启动在启动之前运行的位置服务 应用程序的终止。当您重新启动这些服务时,位置 manager将所有挂起的位置更新传递给其代理

编辑2:

基于此,位置应至少每15分钟更新一次。我的代码中的错误得到了确认

如果GPS水平精度对您的应用程序不重要,并且您不需要 连续跟踪,您可以使用重大更改位置 服务重要的是你要使用重要的变更位置 服务正确,因为它至少会唤醒系统和应用程序 每15分钟一次,即使没有发生位置变化 持续运行,直到您停止

edit3:将此代码添加到AppDelegate
didFinishLaunchingWithOptions:
,以查看应用程序是否被唤醒。它没有被唤醒——我在表视图中没有看到200个条目。有些可疑的事情正在发生

 if let options = launchOptions {
            print("options")
            if (launchOptions![UIApplicationLaunchOptionsLocationKey] != nil){
                locationManager.startUpdatingLocation()
                self.lat.append(Double(200))
                self.lon.append(Double(200))
                self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
                NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
                NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
                NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
            }
代码: //AppDelegate:

import UIKit
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

    var lat:[CLLocationDegrees]!
    var lon:[CLLocationDegrees]!
    var times:[String]!
    var distances: [String]!

    var window: UIWindow?
    var locationManager: CLLocationManager!


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        locationManager=CLLocationManager()
        locationManager.delegate=self
        locationManager.requestAlwaysAuthorization()

        let isFirstLaunch = NSUserDefaults.standardUserDefaults().objectForKey("lat")
        if isFirstLaunch == nil{
            lat = [CLLocationDegrees]()
            lon = [CLLocationDegrees]()
            times = [String]()
            NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
            NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
            NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
        }else{
            lat = NSUserDefaults.standardUserDefaults().arrayForKey("lat") as! [CLLocationDegrees]
            lon = NSUserDefaults.standardUserDefaults().arrayForKey("lon") as! [CLLocationDegrees]
            times = NSUserDefaults.standardUserDefaults().objectForKey("time") as! [String]
//            distances = NSUserDefaults.standardUserDefaults().objectForKey("distance") as! [String]

        }  
        return true
    }



    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("location updated")

        self.lat.append(locations[0].coordinate.latitude)
        self.lon.append(locations[0].coordinate.longitude)
        self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))

        NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
        NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
        NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")

        print("Location: \(locations[0].coordinate.latitude)   \(locations[0].coordinate.longitude)")
    }

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        print("did change AS")
        switch status {
        case .AuthorizedWhenInUse:
            locationManager.startMonitoringSignificantLocationChanges()
        case .AuthorizedAlways:
            print("to always")
            locationManager.startMonitoringSignificantLocationChanges()
            if lat.count==0{
                self.lat.append((locationManager.location?.coordinate.latitude)!)
                self.lon.append((locationManager.location?.coordinate.longitude)!)

                self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))

                NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
                NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
                NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")


            }

//            locationManager.startUpdatingLocation()
            break
        default:
            locationManager.stopMonitoringSignificantLocationChanges()
            break
        }
    }
}
//视图控制器

import UIKit

class TableViewController: UITableViewController {

    let appDel = UIApplication.sharedApplication().delegate as! AppDelegate

    override func viewDidLoad() {
        super.viewDidLoad()

        NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: "updateTableView", userInfo: nil, repeats: true)
    }



    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return appDel.lon.count
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("ID", forIndexPath: indexPath)
        cell.textLabel?.text = "\(appDel.lat[indexPath.row])   \(appDel.lon[indexPath.row])    \(appDel.times[indexPath.row])"
        cell.textLabel?.font = UIFont.systemFontOfSize(9)


        return cell
    }

    func updateTableView(){
    self.tableView.reloadData()
    }
}

我想不管你在哪里,你都得开始约会?您是否尝试过插入断点以查看到达的位置?

代码有几个问题:

  • iOS启动应用程序时不会启动位置更新
  • 不请求后台位置更新
  • 代码依赖于授权状态的更改来启动位置更新
  • didChangeAuthorizationStatus方法中缺少中断语句
  • 有关文件如下:

    第一个文档说,当iOS启动应用程序时,必须完全配置location manager对象,以便将location事件传递到应用程序

    重新启动后,您仍必须配置位置管理器对象并调用此方法[StartMonitoringSignificationLocationChanges]以继续接收位置事件

    我通常是这样做的,以确保位置管理器完全启动,无论它是从图标还是通过iOS启动的(抱歉,我使用ObjectiveC)

    注意调用setAllowsBackgroundLocationUpdates。这在iOS9中是新的,如果您希望在后台接收位置更新,则必须在每次应用启动时执行。(这就像是一句“我不是开玩笑,我知道我在后台模式下要求它们,但我真的想要它们”)

    要在挂起时接收位置更新的应用程序必须在其应用程序的Info.plist文件中包含UIBackgroundModes键(带有位置值),并将此属性的值设置为“是”

    最后,您不能依赖调用didChangeAuthorizationStatus。如果您具有授权KClauthorizationStatusAuthorizationDalways,则调用[locationMgr requestAlwaysAuthorization]不会导致授权状态的更改,因此不会调用didChangeAuthorizationStatus

    如果在调用RequestWhenUseAuthorization或requestAlwaysAuthorization方法时已知道授权状态,则位置管理器不会向此方法报告当前授权状态


    你真的看到授权申请了吗?如果没有,您的plist中是否有NSLocationAlwaysUsageDescription?是,请求会弹出。是的,在info.plist中设置了NSLocationAlwaysUsageDescription字符串。您是否通过双击home按钮并向上滑动应用程序来终止应用程序?如果你以这种方式杀死一个应用程序,它将不会运行后台重要的更改服务。是的,我正在这样做。我认为大多数用户也经常这样做。是否有更好的方法来挂起应用程序?不,这不会挂起应用程序,会完全终止应用程序并阻止进一步的后台交互。不要关闭应用程序,只需点击home按钮一次,然后转到另一个应用程序,而不关闭另一个应用程序。如果我将startUpdatingLocation设置为true,则每秒会更新3次。我认为这只是标准的定位服务。我没有,因为它在模拟器上工作得很好。是否可以在后台的挂起应用程序上使用断点?@krompir2-不,在这种情况下不能使用断点。我通常
    NSLog
    消息(因此我可以观看控制台)。我还发现,将消息记录到一些持久性存储中,然后当我将应用程序置于前台时,将这些保存的消息显示在表视图或类似的视图中,这是很有用的,因此,我可以诊断应用程序不在前台时发生的情况。您可以在挂起或甚至未运行的进程上设置断点。如果进程挂起,请在Xcode中单击调试菜单并选择“附加到进程”-选择您的进程。您现在已连接,并且当进程
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
      NSLog(@"app launching");
      bgTask = UIBackgroundTaskInvalid;
    
      locationMgr = [[CLLocationManager alloc] init];
      [locationMgr setDelegate:self];
      if([locationMgr respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
        [locationMgr setAllowsBackgroundLocationUpdates:YES];
      CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
    
      if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
        NSLog(@"relaunching because of significant location change - restarting SLC");
        [locationMgr startMonitoringSignificantLocationChanges];
      }
      else
      {
        if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
            NSLog(@"launching with authorization to always use location - starting SLC");
            [locationMgr startMonitoringSignificantLocationChanges];
        }
        else
        {
            NSLog(@"launching with no authorization to always use location - requesting authorization");
            if([locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)])
                [locationMgr requestAlwaysAuthorization];
        }
      }
    
      return YES;
    }