2

NSTimer でこれを作成する方法は知っていますが、数秒ごとにタイマーをオンにせずに現在の iPhone 座標を取得したくありません。アプリケーションがバックグラウンドにあるときに座標を取得しているため、タイマーを使用できません。
私は何かを試しましたが、これは10秒ごとではなく毎秒呼び出します。
ここで何が間違っていますか?

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

    NSDate* eventDate = loc.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (howRecent < 10)
    {
        CLLocation* location = [locations lastObject];

        double lat = location.coordinate.latitude;
        double lng = location.coordinate.longitude;
        NSLog(@"lat:%f lng:%f", lat, lng);

最初に 10 秒ごとにバックグラウンド タスクを実行しようとしますが、ここで何かを行うと時間を設定する場所がわかりません。

- (void)applicationDidEnterBackground:(UIApplication *)application
{

    backgroundTask = [application beginBackgroundTaskWithExpirationHandler: ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                [application endBackgroundTask:backgroundTask];
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        _pendingLocationsTimer = [NSTimer timerWithTimeInterval:_pendingLocationsTimerDuration
                                                         target:self
                                                       selector:@selector(_acceptBestAvailableLocation:)
                                                       userInfo:nil repeats:NO];


        NSRunLoop *loop = [NSRunLoop currentRunLoop];
        [loop addTimer:_pendingLocationsTimer forMode:NSRunLoopCommonModes];
        [loop run];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                // if you don't call endBackgroundTask, the OS will exit your app.
                [application endBackgroundTask:backgroundTask];
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    });

}
4

2 に答える 2

2

バックグラウンド状態のタイマーに問題がありました。アクティブな実行ループがあるという保証はないため、フォアグラウンドに戻るまでタイマーは起動しません。私がしたことは次のとおりです。

 NSRunLoop *loop = [NSRunLoop currentRunLoop];
 [loop addTimer:myTimer forMode:NSRunLoopCommonModes];
 [loop run];

これは、BackgroundIdentifierTask の begin 呼び出しと end 呼び出し内のバックグラウンド スレッドで行います。私はそれがすべて正しいと完全に確信しているわけではありません.実際、あなたの質問を見て、要件の理解を確認または修正するのに役立つかどうかを確認しました.

また、ロケーションを継続的に監視する場合は、デフォルトの info.pList でロケーション サービスのバックグラウンド モードを有効にする必要があります。significantLocationUpdates または geofence を使用しているだけの場合は、その必要はありません。

私のタイマーは機能し、このように意図したとおりに起動します。それ以前は、確実に機能しませんでした。

それを除けば、タイマーを使わない方がいいかもしれません。上記のコードを使用して、ロケーション マネージャーのプロパティを変更するだけです。必要な精度と距離フィルターは、マネージャーが新しい場所の通知を送信する頻度を減らすプロパティです。

興味のある方は、github に投稿したばかりの私自身のロケーション ハンドラーの例を参照してください。

http://github.com/dsdavids/TTLocationHandler

タイマーは重要ではないと思います。プロジェクトに TTLocationHandler クラスをドロップした場合は、LMViewController クラスがハンドラーにどのように応答するかを確認してください。

NSNotificationCenter *defaultNotificatoinCenter = [NSNotificationCenter defaultCenter];
[defaultNotificatoinCenter addObserver:self selector:@selector(handleLocationUpdate) name:LocationHandlerDidUpdateLocation object:nil];

コントローラーをオブザーバーとして設定します。新しい場所またはより正確な場所を受信したとハンドラーが判断するたびに、handleLocationUpdate が呼び出されます。

locationManager は、startUpdating が呼び出されると、最初は 1 秒ごとに多くの新しい場所を送信し、デバイスが静止して精度が達成されるまで移動します。TTLocationHandlerはこれらのイベントをフィルタリングし、構成に基づいて必要に応じて通知のみを送信します。

-(id)init では、_recencyThreshold が 60 に設定されていることに注意してください。したがって、60 秒ごとにピンを保存または表示しています。より短い間隔が必要な場合は、これを変更します。

現状では、TTLocationHandler は、デバイスが電源に接続されていない限り、バックグラウンドで常に重要な場所の変更に切り替えます。バッテリー電源を使用している場合、更新の間隔はそれほど短くはありませんが、更新は取得されます。

課金なしで継続的なバックグラウンド更新を構成するためのプロパティを追加しました。

TTLocationHandler の使用例

my ハンドラーを使用して目標を達成する方法を示すために、リポジトリに別のクラスを追加しました。場所を保存およびアップロードするためのコードを追加できる LMPinTracker クラスを追加しました。

LMAppDelegate.m を見てください。

    self.pinTracker.uploadInterval = 30.00;

これをサーバーへのアップロードの間隔に変更します。

    self.sharedLocationHandler.recencyThreshold = 5.0;

その 5.0 を、保存された場所の間に必要な最小時間に変更します。正確ではなく、移動速度と信号強度によって異なりますが、基本的には、x 秒間隔が経過すると、保存された場所が古いと見なされ、別の正確な場所を取得しようとします。

次に、LMPinTracker.m ファイルを見て
ください。次の 2 行の直後にデータ格納コードを配置します。

    // Store the location into your sqlite database here
    NSLog(@"Received location info: %@ \n Ready for store to database",lastKnowLocationInfo);

このコメントの直後に Web アップロード コードを配置します。

    // Do your upload to web operations here

コメント

これは、ユーザーのバッテリーとバックグラウンド操作を考慮しながら、目的の操作を行う必要があります。

基本的に、ユーザーが移動している場合、設定した間隔で更新が継続されます。
ユーザーが静止している場合、更新も重要なアクティビティもありません。
新しいアクティビティがない場合は、Web にもアップロードしません。
ユーザーが再び移動を開始すると、ログ記録と更新が再開されます。

私があなたの場合、さらに絞り込みたい場合は、地域と時間を設定して確認することを検討します。ユーザーが長時間静止している場合は、scientificLocationUpdates のみに切り替えます。次に、位置情報サービスの電源をオフにしますが、ユーザーが再び開始すると元に戻ります.

于 2012-10-11T14:54:04.703 に答える
0

タイマーを使用してバックグラウンドで実行できると思います:

[NSTimer scheduledTimerWithTimeInterval:kAlertInterval target:self selector:@selector(checkLoc:) userInfo:nil repeats:YES];

そしてあなたの方法では:

- (void)checkLoc:(NSTimer *)timer {
    //...get your location and...
     if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
        //Do your background stuff
    }
}

このコードはいくつかのアプリで動作しています。それがあなたのために働くかどうか教えてください。

于 2012-10-11T14:11:27.160 に答える