2016-02-17 14 views
6

重要なロケーションの変更監視を使用しています。シミュレータでコードを実行し、Freewayオプションをチェックすると、私は定期的な位置更新を取得します。これらの更新を取得してNSUserDefaultsに保存し、10秒ごとに更新するようにしたので、更新があるかどうか確認できます。私が実際のデバイスでアプリを実行すると、私はゼロ更新を得る。私は携帯電話をポケットに入れて、80km以上旅行し、2都市にいた。ゼロ更新。私は何かを台無しにしたかどうかは分かりません。私はコードを添付しています。コードはコピー貼り付けですので、自由にテストしてください。ストーリーボードでTableViewControllerを使用し、セルIDをIDに設定してください。私は何が欠けていますか?重要なロケーションの変更がデバイスでトリガーされない

enter image description here

編集:リンゴのドキュメントでこれを見つけた私は、iPhone上で5

するinfo.plistをテストしています。 locationManagerを別様に作成する必要がありますか? willFinishLaunchingWithOptions:または アプリケーション:didFinishLaunchingWithOptions:メソッドが UIApplicationLaunchOptionsLocationKeyキーが含まれているアプリがあるため、位置更新のリニューアルされた場合

、打ち上げ のオプションは、あなたの アプリケーションに渡される辞書です。そのキーが存在すると、新しい場所データがアプリに配信されるのを待っていることが通知されます。 は、そのデータを取得するには、新しいCLLocationManagerオブジェクト を作成して、あなたの アプリの終了に先立って実行していた場所のサービスを再起動する必要があります。これらのサービスを再起動すると、位置 は、保留中のすべてのロケーション更新をそのデリゲートに配信します。

EDIT2:

これに基づき、場所は、少なくともすべての15分を更新する必要があります。私のコードのバグが確認されました。

GPSレベルの精度はアプリの重要ではなく、あなたが 連続追跡を必要としない場合は、大幅な変更位置 サービスを使用することができます。あなたはそれを停止するまで、それは継続的に 実行し、それは何の場所の変更が生じていない場合でも、15分ごとに少なくとも システム、アプリを目覚めるので、あなたは正しく大幅変更位置 サービスを使用することが重要だし、それ。

edit3:このコードをAppDelegate didFinishLaunchingWithOptions:に追加して、アプリが起動するかどうかを確認します。それは目を覚まさない - 私はテーブルビューで200 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") 
      } 

CODE: // 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() 
    } 
} 
+0

実際に承認のリクエストが表示されますか?そうでなければ、plistにNSLocationAlwaysUsageDescriptionがありますか? –

+0

はいリクエストがポップアウトします。また、NSLocationAlwaysUsageDescription文字列はinfo.plistに設定されています。 – brumbrum

+0

ホームボタンを2回タップしてアプリを殺して、アプリをスワップアップしていますか?そうした方法でアプリを削除すると、重要な変更サービスがバックグラウンドで実行されることはありません。 – Rob

答えて

14

は、コードにはいくつかの問題があります。

  1. アプリがiOS版で起動したときに更新が開始されていない場所。
  2. バックグラウンドの場所の更新は要求されません。
  3. コードがdidChangeAuthorizationStatus方法で不足しているbreak文がある位置情報の更新
  4. を開始するために認証ステータスの変化に依存しています。

ここでは、関連する文書である:

最初の文書はiOSのアプリを起動したときにロケーションマネージャオブジェクトが完全に設定する必要がありますと言いますロケーションイベントをアプリに配信することができます。

ロケーションマネージャのオブジェクトを設定してから、このメソッド[startMonitoringSignificantLocationChanges]を呼び出して、ロケーションイベントを引き続き受信する必要があります。

これは、アイコンやiOSから起動されたかどうかに関係なく、ロケーションマネージャが完全に起動するようにするためです(ObjectiveCを使用して申し訳ありません)。

- (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; 
} 

setAllowsBackgroundLocationUpdatesへの呼び出しに注目してください。これはiOS9の新機能で、バックグラウンドで場所の更新を受信する場合には、アプリが起動するたびに実行する必要があります。 (私は冗談ではない、私はバックグラウンドモードでそれらを求めているが、実際には彼らを欲しいと思う)。

停止時に位置の更新を受け取りたいアプリケーションは、アプリのInfo.plistファイルにUIBackgroundModesキー(位置値付き)を含め、このプロパティの値をYESに設定する必要があります。

最後に、didChangeAuthorizationStatusが頼りになることはありません。あなたが承認kCLAuthorizationStatusAuthorizedAlwaysを持っている場合は、[locationMgr requestAlwaysAuthorization]を呼び出すと、認証状態の変化をもたらさないので、didChangeAuthorizationStatusは呼び出されません。

承認ステータスは、すでにあなたがrequestWhenInUseAuthorizationまたはrequestAlwaysAuthorizationメソッドを呼び出すと、ロケーションマネージャは、この方法には、現在の認証ステータスを報告しないわかっている場合。

+0

先生、あなたは100万の票を獲得する必要があります。ありがとうございました! – brumbrum

+0

問題はありません - アップルは、CoreLocationをiOSのすべてのリリースで正しく使用することを着実に困難にしています。私はそれがiOS6の周りに完璧だったと思う、今それはただの秘訣だ。あなたのプロジェクトに幸運。 – BitByteDog

+1

それを主張することはできません。サイドノート。私は数日の間、今遊んできました。実際の場所の変更にかかわらず、重要な場所は少なくとも15分ごとに起動されるとAppleはアドバイスしています。私は移動していない場合、私は更新を取得していません。あなたが移動していなくても、15分ごとにあなたのアプリで位置更新を見ていますか? – brumbrum

0

私はあなたが関係なく、startUpdatingLocationする必要があると思いますか?ブレークポイントを挿入してどこにアクセスしてみましたか?

+0

startUpdatingLocationをtrueに設定すると、毎秒3回更新されます。私はそれが標準的な位置情報サービスのための唯一のものだと思う。私はそれがシミュレータ上でうまく動作するので、持っていない。 – brumbrum

+0

バックグラウンドで中断しているアプリでブレークポイントを使用することはできますか? – brumbrum

+0

@ krompir2 - いいえ、この場合はブレークポイントを使用できません。私は一般的に 'NSLog'メッセージ(私はコンソールを見ることができます)。私はまた、いくつかの永続的なストレージにメッセージを記録し、私はフォアグラウンドにアプリケーションを持って来ると便利であることが判明した、これらの保存されたメッセージをテーブルビューまたはそのようなもので表示するので、前景。 – Rob

関連する問題