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] 
}

实际位置经理委托:

内部GPSManager.h:

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

内部GPSManager.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

问题是您在后台线程中开始位置更新,然后在您告诉位置更新开始时立即清理。

detachNewThreadSelector:toTarget:withObject:来自Apple 文档

对象 aTarget 和 anArgument 在分离线程执行期间被保留,然后被释放。一旦 aTarget 完成执行 aSelector 方法,分离的线程就会退出(使用 exit 类方法)。

因此,一旦您startLocationUpdate完成,该线程就会被清理。

然后,从位置管理器委托上的这些其他 Apple 文档中:

您的委托对象的方法是从您启动相应位置服务的线程中调用的。该线程本身必须有一个活动的运行循环,就像在应用程序的主线程中找到的那样

因此,他们CLLocationManager希望在您启动它们的同一线程(调用的线程startUpdatingLocation)上用位置更新给您回电,但是当位置修复可用时,该线程可能已经消失。我还可以相信,您可以在一个设备/操作系统上使用代码而不是在另一个设备/操作系统上幸运。

所以,要么:

  • 在主线程上启动位置更新。开始位置更新是一个异步操作,所以仅仅因为您在主 (UI) 线程上执行此操作,并不意味着整个 UI 被阻塞,直到位置修复可用。这只是意味着当位置可用时,您将在 UI 线程上被回调。

或者 ...

  • 只要您想继续接收位置更新,就让您的后台线程一直存在

做第一个,做这个

[self.locationManager startUpdatingLocation]; 

而不是调用startLocationUpdateInSeparateThread. 要执行第二个,请添加以下代码:

- (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 回答