22

我已经知道如何使用 CLLocationManager,所以我可以通过委托和所有其他方式来做这件事。

但是我想要一个方便的方法,它只获取当前位置一次,然后阻塞直到它得到结果。

4

5 回答 5

44

我所做的是实现一个单例类来管理来自核心位置的更新。要访问我当前的位置,我会执行CLLocation *myLocation = [[LocationManager sharedInstance] currentLocation]; 如果您想阻止主线程,您可以执行以下操作:

while ([[LocationManager sharedInstance] locationKnown] == NO){
   //blocking here
   //do stuff here, dont forget to have some kind of timeout to get out of this blocked    //state
}

然而,正如已经指出的那样,阻塞主线程可能不是一个好主意,但是当你正在构建一些东西时,这可能是一个很好的起点。您还会注意到我编写的类检查位置更新的时间戳并忽略任何旧的,以防止从核心位置获取陈旧数据的问题。

这是我写的单例类。请注意,边缘有点粗糙:

#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>

@interface  LocationController : NSObject <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
    CLLocation *currentLocation;
}

+ (LocationController *)sharedInstance;

-(void) start;
-(void) stop;
-(BOOL) locationKnown;

@property (nonatomic, retain) CLLocation *currentLocation;

@end
@implementation LocationController

@synthesize currentLocation;

static LocationController *sharedInstance;

+ (LocationController *)sharedInstance {
    @synchronized(self) {
        if (!sharedInstance)
            sharedInstance=[[LocationController alloc] init];       
    }
    return sharedInstance;
}

+(id)alloc {
    @synchronized(self) {
        NSAssert(sharedInstance == nil, @"Attempted to allocate a second instance of a singleton LocationController.");
        sharedInstance = [super alloc];
    }
    return sharedInstance;
}

-(id) init {
    if (self = [super init]) {
        self.currentLocation = [[CLLocation alloc] init];
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        [self start];
    }
    return self;
}

-(void) start {
    [locationManager startUpdatingLocation];
}

-(void) stop {
    [locationManager stopUpdatingLocation];
}

-(BOOL) locationKnown { 
     if (round(currentLocation.speed) == -1) return NO; else return YES; 
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    //if the time interval returned from core location is more than two minutes we ignore it because it might be from an old session
    if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 120) {     
        self.currentLocation = newLocation;
    }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    UIAlertView *alert;
    alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[error description] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

-(void) dealloc {
    [locationManager release];
    [currentLocation release];
    [super dealloc];
}

@end
于 2009-01-20T20:27:16.583 回答
7

没有这样的便利,您不应该创建自己的。“在得到结果之前一直阻塞”在 iPhone 这样的设备上是非常糟糕的编程习惯。检索位置可能需要几秒钟;你永远不应该让你的用户那样等待,并且代表确保他们不会。

于 2009-01-22T09:53:38.997 回答
4

除非您自己编写代码,否则没有“方便方法”,但您仍然需要在任何自定义代码中实现委托方法,以使事情变得“方便”。

委托模式的存在是有原因的,因为委托是 Objective-C 的重要组成部分,我建议你熟悉它们。

于 2009-01-20T01:15:29.047 回答
0

我感谢布拉德史密斯的回答。实施它我发现他使用的其中一种方法在 iOS6 中已被弃用。要编写适用于 iOS5 和 iOS6 的代码,请使用以下代码:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    if (abs([[locations lastObject] timeIntervalSinceDate:[NSDate date]]) < 120) {
        [self setCurrentLocation:[locations lastObject]];
    }
}

// Backward compatibility with iOS5.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSArray *locations = [NSArray arrayWithObjects:oldLocation, newLocation, nil];
    [self locationManager:manager didUpdateLocations:locations];
}
于 2013-06-29T03:41:02.303 回答
0

我简化并组合了多个答案,仅当位置有效时才更新位置。

它也适用于 OSX 和 iOS。

这假设了用户突然需要当前位置的用例。如果在此示例中花费超过 100 毫秒,则将其视为错误。(假设 GPS IC 和| Wifi(Apple 的 Skyhook 克隆)已经启动并且已经有了很好的修复。)

#import "LocationManager.h"

// wait up to 100 ms
CLLocation *location = [LocationManager currentLocationByWaitingUpToMilliseconds:100];
if (!location) {
    NSLog(@"no location :(");
    return; 
}
// location is good, yay

https://gist.github.com/6972228

于 2013-10-14T08:20:55.580 回答