1

私の AppDelegate には、次のプロパティがあります。

GPSTracking*        _GPSTracker;

場所の更新を開始する責任があります。シングルトンCLLocationManagerDelegateを使用し、次のように使用します。

@implementation GPSTracking

-(id) initWithDelegate:(MSpyAppDelegate *) _del
{
    if (self = [super init])
    {   
        self.mainDelegate = _del;
        [[InternalGPSManager sharedInstance] setMainDelegate: self.mainDelegate];
    }
    return self;
}

//Start getting locations
- (void)startUpdatingByManager
{
    [[InternalGPSManager sharedInstance] startLocationUpdateInSeparateThread];
    self.gpsTimer = [NSTimer scheduledTimerWithTimeInterval:(gpsUpdateInterval * 60)    target:self selector:@selector(startUpdatingByManager) userInfo:nil repeats:NO] 
}

実際のロケーション マネージャー デリゲート:

InternalGPSManager.h:

@interface InternalGPSManager : NSObject <CLLocationManagerDelegate>
   {
      CLLocationManager *locationManager;
   }
@property (nonatomic, retain) CLLocationManager *locationManager;

InternalGPSManager.m

static InternalGPSManager *sharedCLDelegate = nil;
@implementation InternalGPSManager
@synthesize locationManager;


- (id)init
{
    self = [super init];

    if (self != nil) 
    {
        self.locationManager = [[[CLLocationManager alloc] init] autorelease];
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    }

    return self;
}
    - (void)startLocationUpdateInSeparateThread
    {
        [NSThread detachNewThreadSelector:@selector(startLocationUpdate) toTarget:self withObject:nil];
    }
    - (void)startLocationUpdate
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        [self.locationManager startUpdatingLocation];

        [pool release];
    }

iOS 4 では動作しますが、iOS 5 では動作しません。ロケーション デリゲート コールバックは呼び出されません。何か案は?

4

2 に答える 2

1

問題は、バックグラウンド スレッドで位置情報の更新を開始していて、位置情報の更新を開始するように指示するとすぐにクリーンアップされることです。

Apple ドキュメントからdetachNewThreadSelector:toTarget:withObject::

オブジェクト aTarget および anArgument は、切り離されたスレッドの実行中に保持され、その後解放されます。切り離されたスレッドは、aTarget が aSelector メソッドの実行を完了するとすぐに (exit クラス メソッドを使用して) 終了します。

したがって、startLocationUpdate完了するとすぐに、そのスレッドはクリーンアップされます。

次に、ロケーション マネージャー デリゲートに関するこれらの他の Apple ドキュメントから:

デリゲート オブジェクトのメソッドは、対応するロケーション サービスを開始したスレッドから呼び出されます。そのスレッド自体に、アプリケーションのメイン スレッドにあるようなアクティブな実行ループが必要です。

そのため、 は、CLLocationManagerあなたがそれらを開始したのと同じスレッド ( を呼び出したスレッドstartUpdatingLocation) の位置の更新であなたに電話をかけ直したいと考えていますが、位置の修正が利用可能になるまでにそのスレッドはなくなっている可能性があります。また、別のデバイスや OS ではなく、あるデバイスや OS のコードで幸運に恵まれることあると信じています。

したがって、次のいずれかです。

  • メイン スレッドで位置情報の更新を開始します。位置情報の更新の開始は非同期操作であるため、メイン (UI) スレッドで開始したからといって、位置情報の修正が利用可能になるまで UI 全体がブロックされるわけではありません。これは、場所が利用可能になると、UI スレッドでコールバックされることを意味します。

または ...

  • 位置情報の更新を受信し続ける限り、バックグラウンド スレッドをハングアップさせます

最初に行うには、これを行うだけです

[self.locationManager startUpdatingLocation]; 

を呼び出す代わりにstartLocationUpdateInSeparateThread。2 番目を行うには、次のコードを追加します。

- (void)startLocationUpdate 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    [self.locationManager startUpdatingLocation]; 

    [[NSRunLoop currentRunLoop] run];  // keep this background thread from being cleaned up

    [pool release]; 
} 

CLLocationManagerDelegateコールバック (位置情報の更新を受信するため) が重い処理を行わない場合は、バックグラウンド スレッドを完全に回避することをお勧めします 。

于 2012-07-25T02:02:04.293 に答える
1

ユーモアを交えて、コードを次のように変更してみてください。

- (void)startLocationUpdateInSeparateThread
{
   // Not a separate thread!
   NSLog(@"Starting updates using delegate: %@", self.locationManager.delegate);
   [self.locationManager startUpdatingLocation];
}

PS: なぜ ARC を使用しないのですか???

于 2012-07-24T17:08:22.300 に答える