web-dev-qa-db-ja.com

iOSアプリケーションでn分ごとに背景の位置情報を更新するにはどうすればよいですか。

私のiOSアプリケーションでは、n分ごとに背景の位置情報を更新する方法を探しています。私はiOS 4.3を使用していますが、このソリューションは非脱獄iPhone用に機能するはずです。

私は以下のオプションを試してみました/考えました:

  • CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges:これは設定されたプロパティに基づいて予想通りバックグラウンドで動作しますが、n分ごとに位置を更新するように強制することは不可能のようです
  • NSTimer:アプリがフォアグラウンドで実行されていてもバックグラウンドタスク用に設計されていないような場合には機能します。
  • ローカル通知:ローカル通知はn分ごとにスケジュールすることができますが、現在の位置を取得するためにコードを実行することはできません(通知を介してユーザーがアプリを起動しなくても)。これは通知を使用すべきものではないため、このアプローチもクリーンなアプローチではないようです。
  • UIApplication:beginBackgroundTaskWithExpirationHandler:私が理解している限りでは、これは "長時間実行"バックグラウンドプロセスを実装するのではなく、アプリがバックグラウンドに移動したときにバックグラウンドで作業を終了するために使用されるべきです。

これらの定期的なバックグラウンドロケーションの更新を実装する方法

199
wjans

私はアップルデベロッパフォーラムの助けを借りてこれを実装するための解決策を見つけました:

  • location background modeを指定してください
  • UIApplication:beginBackgroundTaskWithExpirationHandler:を使ってバックグラウンドでNSTimerを作成します
  • nUIApplication:backgroundTimeRemainingよりも小さいの場合は、うまく動作します。 nより大きいの場合は、バックグラウンドタスクが強制終了されるのを防ぐための残り時間がなくなる前に、location managerを再度有効(および無効)にする必要があります。

これは、locationがバックグラウンド実行で許可されている3つのタイプのうちの1つであるため機能します。

注:シミュレータでこれが機能しない場所でテストすることで時間を無駄にしました。ただし、私の携帯電話では正常に機能します。

112
wjans

On iOS 8/9/1 5分ごとに背景の位置情報を更新するには、次の操作を行います。

  1. [プロジェクト] - > [機能] - > [バックグラウンドモード] - > [ロケーションの更新]を選択します。

  2. [プロジェクト] - > [情報] - > [NSLocationAlwaysUsageDescription]に空の値(または任意のテキスト)を追加します。

  3. アプリがバックグラウンドで動作しているときに位置情報を機能させ、Webサービスに座標を送信したり、5分ごとにそれらを使用したりするには、次のコードのように実装します。

私はバックグラウンドタスクやタイマーを使用していません。私のアプリがバックグラウンドで実行されている状態で数時間私の机の上に横たわっていたiOS 8.1で私のデバイスでこのコードをテストしました。デバイスはロックされており、コードは常に正しく実行されていました。

@interface LocationManager () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) NSDate *lastTimestamp;

@end

@implementation LocationManager

+ (instancetype)sharedInstance
{
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        LocationManager *instance = sharedInstance;
        instance.locationManager = [CLLocationManager new];
        instance.locationManager.delegate = instance;
        instance.locationManager.desiredAccuracy = kCLLocationAccuracyBest; // you can use kCLLocationAccuracyHundredMeters to get better battery life
        instance.locationManager.pausesLocationUpdatesAutomatically = NO; // this is important
    });

    return sharedInstance;
}

- (void)startUpdatingLocation
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    if (status == kCLAuthorizationStatusDenied)
    {
        NSLog(@"Location services are disabled in settings.");
    }
    else
    {
        // for iOS 8
        if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
        {
            [self.locationManager requestAlwaysAuthorization];
        }
        // for iOS 9
        if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
        {
            [self.locationManager setAllowsBackgroundLocationUpdates:YES];
        }

        [self.locationManager startUpdatingLocation];
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *mostRecentLocation = locations.lastObject;
    NSLog(@"Current location: %@ %@", @(mostRecentLocation.coordinate.latitude), @(mostRecentLocation.coordinate.longitude));

    NSDate *now = [NSDate date];
    NSTimeInterval interval = self.lastTimestamp ? [now timeIntervalSinceDate:self.lastTimestamp] : 0;

    if (!self.lastTimestamp || interval >= 5 * 60)
    {
        self.lastTimestamp = now;
        NSLog(@"Sending current location to web service.");
    }
}

@end
53
Leszek Szary

私が開発しているアプリケーションでこれを行いました。アプリがバックグラウンドで動作していてもアプリが常に位置情報を受信して​​いる場合、タイマーは機能しません。私はドキュメントのどこかに読んでいます(今は見つからないようですが、更新があるときは更新を投稿します)。アプリがバックグラウンドで実行されているときは、アクティブな実行ループでしか呼び出せません。あなたがこの仕事をするためにあなた自身のものを作成する必要がないように、アプリデリゲートはbgでもアクティブな実行ループを持っています。 [これが正しい説明であるかどうかはわかりませんが、私が読んだものから理解した方法です。]

まず、アプリのinfo.plistにキーlocationUIBackgroundModesオブジェクトを追加します。今、あなたがする必要があるのはあなたのアプリのどこかに位置の更新を開始することです:

    CLLocationManager locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;//or whatever class you have for managing location
    [locationManager startUpdatingLocation];

次に、アプリのデリゲートで、位置の更新を処理するメソッド(-(void)didUpdateToLocation:(CLLocation*)locationなど)を作成します。次に、ロケーションマネージャを起動したクラスにCLLocationManagerDelegateのメソッドlocationManager:didUpdateLocation:fromLocationを実装します(ロケーションマネージャのデリゲートを 'self'に設定しているため)。この方法の中では、位置の更新を処理しなければならない時間間隔が経過したかどうかを確認する必要があります。毎回現在時刻を保存することでこれを行うことができます。その時間が経過したら、アプリデリゲートからメソッドUpdateLocationを呼び出します。

NSDate *newLocationTimestamp = newLocation.timestamp;
NSDate *lastLocationUpdateTiemstamp;

int locationUpdateInterval = 300;//5 mins

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (userDefaults) {

        lastLocationUpdateTiemstamp = [userDefaults objectForKey:kLastLocationUpdateTimestamp];

        if (!([newLocationTimestamp timeIntervalSinceDate:lastLocationUpdateTiemstamp] < locationUpdateInterval)) {
            //NSLog(@"New Location: %@", newLocation);
            [(AppDelegate*)[UIApplication sharedApplication].delegate didUpdateToLocation:newLocation];
            [userDefaults setObject:newLocationTimestamp forKey:kLastLocationUpdateTimestamp];
        }
    }
}

アプリがバックグラウンドにある場合でも、5分ごとにメソッドが呼び出されます。 Imp:この実装はバッテリーを消耗します、あなたの位置データの正確さが重要ではないならあなたは[locationManager startMonitoringSignificantLocationChanges]を使うべきです

これをアプリに追加する前に、 位置認識プログラミングガイド をお読みください。

35
Bushra Shahid

今iOS6は永遠に実行されている位置情報サービスを持っているための最善の方法ではありません...

- (void)applicationWillResignActive:(UIApplication *)application
{
/*
 Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
 Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
 */

NSLog(@"to background");

app.isInBackground = TRUE;

UIApplication *app = [UIApplication sharedApplication];

// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    // Synchronize the cleanup call on the main thread in case
    // the task actually finishes at around the same time.
    dispatch_async(dispatch_get_main_queue(), ^{

        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }
    });
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

    locationManager.distanceFilter = 100;
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    [locationManager startMonitoringSignificantLocationChanges];
    [locationManager startUpdatingLocation];

    NSLog(@"App staus: applicationDidEnterBackground");
    // Synchronize the cleanup call on the main thread in case
    // the expiration handler is fired at the same time.
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }
    });
});

NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);

}

ちょうどそれをそのようにテストしました:

私はアプリを起動し、背景に行き、車で数分で移動します。それから私は1時間家に帰り、(再びアプリを開かずに)再び動き始めます。場所は再び始まった。それから2時間停止して、再び始めました。また大丈夫….

IOS6の新しい位置情報サービスの使用を忘れないでください

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{   
    CLLocation *loc = [locations lastObject];

    // Lat/Lon
    float latitudeMe = loc.coordinate.latitude;
    float longitudeMe = loc.coordinate.longitude;
}
24

他の誰かに悪夢を見てこれを理解しています。簡単な解決策があります。

  1. raywenderlich.com - >からこの例を見てください、これは完全に動作しますが、残念ながらバックグラウンド位置の間にタイマーはありません。これは無期限に実行されます。
  2. を使用してタイマーを追加します。

    -(void)applicationDidEnterBackground {
    [self.locationManager stopUpdatingLocation];
    
    UIApplication*    app = [UIApplication sharedApplication];
    
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
    
     self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate
                                                  target:self.locationManager
                                                selector:@selector(startUpdatingLocation)
                                                userInfo:nil
                                                 repeats:YES];
    
    }
    
  3. Info.plistに「位置登録のためのアプリ登録」を追加することを忘れないでください。

13
HelmiB

これが私が使っているものです:

import Foundation
import CoreLocation
import UIKit

class BackgroundLocationManager :NSObject, CLLocationManagerDelegate {

    static let instance = BackgroundLocationManager()
    static let BACKGROUND_TIMER = 150.0 // restart location manager every 150 seconds
    static let UPDATE_SERVER_INTERVAL = 60 * 60 // 1 hour - once every 1 hour send location to server

    let locationManager = CLLocationManager()
    var timer:NSTimer?
    var currentBgTaskId : UIBackgroundTaskIdentifier?
    var lastLocationDate : NSDate = NSDate()

    private override init(){
        super.init()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
        locationManager.activityType = .Other;
        locationManager.distanceFilter = kCLDistanceFilterNone;
        if #available(iOS 9, *){
            locationManager.allowsBackgroundLocationUpdates = true
        }

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.applicationEnterBackground), name: UIApplicationDidEnterBackgroundNotification, object: nil)
    }

    func applicationEnterBackground(){
        FileLogger.log("applicationEnterBackground")
        start()
    }

    func start(){
        if(CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
            if #available(iOS 9, *){
                locationManager.requestLocation()
            } else {
                locationManager.startUpdatingLocation()
            }
        } else {
                locationManager.requestAlwaysAuthorization()
        }
    }
    func restart (){
        timer?.invalidate()
        timer = nil
        start()
    }

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case CLAuthorizationStatus.Restricted:
            //log("Restricted Access to location")
        case CLAuthorizationStatus.Denied:
            //log("User denied access to location")
        case CLAuthorizationStatus.NotDetermined:
            //log("Status not determined")
        default:
            //log("startUpdatintLocation")
            if #available(iOS 9, *){
                locationManager.requestLocation()
            } else {
                locationManager.startUpdatingLocation()
            }
        }
    }
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if(timer==nil){
            // The locations array is sorted in chronologically ascending order, so the
            // last element is the most recent
            guard let location = locations.last else {return}

            beginNewBackgroundTask()
            locationManager.stopUpdatingLocation()
            let now = NSDate()
            if(isItTime(now)){
                //TODO: Every n minutes do whatever you want with the new location. Like for example sendLocationToServer(location, now:now)
            }
        }
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        CrashReporter.recordError(error)

        beginNewBackgroundTask()
        locationManager.stopUpdatingLocation()
    }

    func isItTime(now:NSDate) -> Bool {
        let timePast = now.timeIntervalSinceDate(lastLocationDate)
        let intervalExceeded = Int(timePast) > BackgroundLocationManager.UPDATE_SERVER_INTERVAL
        return intervalExceeded;
    }

    func sendLocationToServer(location:CLLocation, now:NSDate){
        //TODO
    }

    func beginNewBackgroundTask(){
        var previousTaskId = currentBgTaskId;
        currentBgTaskId = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
            FileLogger.log("task expired: ")
        })
        if let taskId = previousTaskId{
            UIApplication.sharedApplication().endBackgroundTask(taskId)
            previousTaskId = UIBackgroundTaskInvalid
        }

        timer = NSTimer.scheduledTimerWithTimeInterval(BackgroundLocationManager.BACKGROUND_TIMER, target: self, selector: #selector(self.restart),userInfo: nil, repeats: false)
    }
}

私はそのようにAppDelegateで追跡を始めます。

BackgroundLocationManager.instance.start()
7
hmitkov

残念ながら、あなたのすべての仮定は正しいように思われます、そして私はこれをする方法があるとは思わない。バッテリーの寿命を節約するために、iPhoneの位置情報サービスは動きに基づいています。電話が一箇所にある場合は、位置情報サービスからは見えません。

CLLocationManagerは、電話機が位置情報の更新を受信したときにのみlocationManager:didUpdateToLocation:fromLocation:を呼び出します。これは、3つの位置情報サービス(cell tower、gps、wifi)の1つが変更を感知した場合にのみ発生します。

さらなる解決策を提供するのに役立つかもしれない他のいくつかのこと:

  • サービスを開始して停止すると、didUpdateToLocationデリゲートメソッドが呼び出されますが、newLocationのタイムスタンプは古い場合があります。

  • 地域モニタリングが役に立つかもしれません

  • バックグラウンドで実行している場合は、「フル」LocationServicesサポートをアップルによって承認されることが難しい場合があることに注意してください。私が見たことから、彼らはバックグラウンド位置のサポートを必要とするアプリケーションのための低消費電力の代替としてstartMonitoringSignificantLocationChangesを特に設計しました、そしてアプリケーションが絶対にそれを必要としない限りこれを使うことを開発者に強く勧めます。

がんばろう!

更新:これらの考えは今では時代遅れかもしれません。あたかも@wjansの答えで人々が成功しているかのように見えます。

6
Chazbot

私は位置情報サービスを使用してアプリを書いたのですが、アプリは10秒ごとに位置情報を送信する必要があります。そしてそれはとてもうまくいった。

Appleのドキュメントに従って、 " allowDeferredLocationUpdatesUntilTraveled:timeout "メソッドを使うだけです。

私がしたことは:

必須:更新場所の背景モードを登録します。

1.LocationMangername__およびstartUpdatingLocationname__を使用して、accuracyname__およびfilteredDistancename__を作成します。

-(void) initLocationManager    
{
    // Create the manager object
    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    _locationManager.delegate = self;
    // This is the most important property to set for the manager. It ultimately determines how the manager will
    // attempt to acquire location and thus, the amount of power that will be consumed.
    _locationManager.desiredAccuracy = 45;
    _locationManager.distanceFilter = 100;
    // Once configured, the location manager must be "started".
    [_locationManager startUpdatingLocation];
}

2.バックグラウンドでallowDeferredLocationUpdatesUntilTraveled:timeoutメソッドを使用してアプリを永遠に実行し続けるには、アプリがバックグラウンドに移動したときにupdatingLocationname__を新しいパラメーターで再起動する必要があります。

- (void)applicationWillResignActive:(UIApplication *)application {
     _isBackgroundMode = YES;

    [_locationManager stopUpdatingLocation];
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [_locationManager setDistanceFilter:kCLDistanceFilterNone];
    _locationManager.pausesLocationUpdatesAutomatically = NO;
    _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
    [_locationManager startUpdatingLocation];
 }

3.AppはlocationManager:didUpdateLocations:コールバックで通常どおりupdatedLocationsを取得します。

-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
    CLLocation *newLocation = [locations lastObject];
    self.userLocation = newLocation;

   //tell the centralManager that you want to deferred this updatedLocation
    if (_isBackgroundMode && !_deferringUpdates)
    {
        _deferringUpdates = YES;
        [self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
    }
}

4。しかしあなたの目的のためにlocationManager:didFinishDeferredUpdatesWithError:コールバックでデータを扱うべきです

- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

     _deferringUpdates = NO;

     //do something 
}

5。注:アプリがbackground/forgroundモードに切り替わるたびにLocationManagername__のパラメータをリセットするべきだと思います。

5
samthui7
if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
    [self.locationManager setAllowsBackgroundLocationUpdates:YES];
}

これはiOS 9以降のバックグラウンド位置追跡に必要です。

5
Nilesh

Xs2bushの間隔を取得する方法(timeIntervalSinceDateを使用)を使用し、それを少し拡張しました。私は必要な正確さを得ていること、そしてGPS無線を必要以上にオンにしておくことによってバッテリーを使い果たしていないことを確かめたかったのです。

次の設定で位置情報を継続的に実行します。

locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locationManager.distanceFilter = 5;

これはバッテリーの消耗が比較的少ないということです。次の定期的な位置情報を取得する準備ができたら、まずその場所が目的の精度内にあるかどうかを確認します。それが正しい場合は、その場所を使用します。そうでなければ、私はこれで精度を上げます:

locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter = 0;

自分の位置を取得してから、その位置を取得したら、精度を再度下げてバッテリーの消耗を最小限に抑えます。私はこれの完全な実例を書きました、そしてまた私は位置データを集めてデータベースにそれを保存してユーザーがリアルタイムでgpsデータを見るかまたは以前に保存されたルートを検索して見ることを可能にするためのサーバーサイドコードのソースを書きました私はiOS、Android、Windows Phone、そしてJavaのクライアントを持っています。すべてのクライアントはネイティブに書かれており、バックグラウンドで正しく機能します。プロジェクトはMITライセンスを受けています。

IOSプロジェクトは、iOS 7の基本SDKを使用してiOS 6をターゲットにしています。ここでコード を入手できます

問題がある場合はgithubに問題を報告してください。ありがとう。

4
nickfox

StopUpdatingLocationがバックグラウンドのウォッチドッグタイマーをトリガーするものと思われるので、didUpdateLocationのdidUpdateLocationを次のように置き換えました。

     [self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
     [self.locationManager setDistanceFilter:99999];

これはGPSを効果的にパワーダウンさせるようです。背景NSTimerのセレクタは次のようになります。

- (void) changeAccuracy {
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

私がしていることは、数分ごとに高精度の座標を得るために定期的に精度を切り替えることです。そしてlocationManagerは停止されていないので、backgroundTimeRemainingはその最大値のままです。これにより、バッテリ消費量が(バックグラウンドで一定のkCLLocationAccuracyBestで)1時間あたりの最大10%から、私のデバイスでの1時間あたりの最大2%に減少しました。

2

Cocoapod APScheduledLocationManager があります。これにより、n秒ごとに希望の位置精度で背景の位置情報を更新できます。

let manager = APScheduledLocationManager(delegate: self)
manager.startUpdatingLocation(interval: 170, acceptableLocationAccuracy: 100)

リポジトリにはSwift 3で書かれたサンプルアプリケーションも含まれています。

2
sash

作業コード(全段階的コード)

ステップ1

  • 「プロジェクト」 - >「機能」 - >「バックグラウンドモード」 - >「ロケーションの更新」の順に選択します。
  • [プロジェクト] - > [情報] - > [NSLocationAlwaysUsageDescription]にオプションの文字列を追加します。

ステップ2

このコードをAppDelegate.mに追加してください。

@interface AppDelegate ()<CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) NSTimer *timer;
@end

ステップこのコードをAppDelegate.mapplicationDidEnterBackgroundメソッドに追加します。

    - (void)applicationDidEnterBackground:(UIApplication *)application {
        UIApplication *app = [UIApplication sharedApplication];
        __block UIBackgroundTaskIdentifier bgTaskId =
        [app beginBackgroundTaskWithExpirationHandler:^{
            [app endBackgroundTask:bgTaskId];
            bgTaskId = UIBackgroundTaskInvalid;
        }];

        dispatch_async( dispatch_get_main_queue(), ^{
            self.timer = nil;
            [self initTimer];
            [app endBackgroundTask:bgTaskId];
            bgTaskId = UIBackgroundTaskInvalid;
        });
    }

- (void)initTimer {
    if (nil == self.locationManager)
        self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    [self.locationManager requestAlwaysAuthorization];
    [self.locationManager startMonitoringSignificantLocationChanges];
    if (self.timer == nil) {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3
                                                      target:self
                                                    selector:@selector(checkUpdates:)
                                                    userInfo:nil
                                                     repeats:YES];
    }
}

- (void)checkUpdates:(NSTimer *)timer{
    UIApplication *app = [UIApplication sharedApplication];
    double remaining = app.backgroundTimeRemaining;
    if(remaining < 580.0) {
        [self.locationManager startUpdatingLocation];
        [self.locationManager stopUpdatingLocation];
        [self.locationManager startMonitoringSignificantLocationChanges];
    }
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    NSLog(@"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude);
    [self updateLocationWithLatitude:[newLocation coordinate].latitude andLongitude:[newLocation coordinate].longitude];
    UIApplication*    app = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier bgTask =
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self initTimer];
    });
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    [self.locationManager stopUpdatingLocation];
    UIApplication *app = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier bgTask =
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
    [self initTimer];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Do the work associated with the task
    });
}

-(void)updateLocationWithLatitude:(CLLocationDegrees)latitude
                     andLongitude:(CLLocationDegrees)longitude{
//Here you can update your web service or back end with new latitude and longitude
}
1
Hari R Krishna

IOS 9およびwatchOS 2.0では、CLLocationManagerに現在の位置を要求できる新しいメソッドがあります。CLLocationManager:requestLocation()。これはすぐに完了し、場所をCLLocationManagerデリゲートに返します。

NSTimerを使用して、このメソッドで毎分ロケーションをリクエストすることができます。startUpdatingLocationメソッドおよびstopUpdatingLocationメソッドを使用する必要はありません。

ただし、最後の位置からXメートルの変化に基づいて位置をキャプチャする場合は、CLLocationMangerのdistanceFilterプロパティを設定し、XにstartUpdatingLocation()を呼び出します。

0
Malcolm