什么';获取iPhone当前位置的最简单方法是什么?
我已经知道如何使用CLLocationManager,所以我可以用很难的方式完成它,有代表和所有这些 但是我希望有一个方便的方法,只获取当前位置,一次,并阻塞,直到得到结果。没有“方便方法”,除非您自己编写它们,但是您仍然需要在任何自定义代码中实现委托方法,以使事情“方便”什么';获取iPhone当前位置的最简单方法是什么?,iphone,core-location,Iphone,Core Location,我已经知道如何使用CLLocationManager,所以我可以用很难的方式完成它,有代表和所有这些 但是我希望有一个方便的方法,只获取当前位置,一次,并阻塞,直到得到结果。没有“方便方法”,除非您自己编写它们,但是您仍然需要在任何自定义代码中实现委托方法,以使事情“方便” 委托模式的存在是有原因的,由于委托是Objective-C的重要组成部分,我建议您熟悉它们。我要做的是实现一个singleton类来管理来自核心位置的更新。要访问我的当前位置,我执行CLLocation*myLocation
委托模式的存在是有原因的,由于委托是Objective-C的重要组成部分,我建议您熟悉它们。我要做的是实现一个singleton类来管理来自核心位置的更新。要访问我的当前位置,我执行
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
#导入
#进口
@接口位置控制器:NSObject{
CLLocationManager*locationManager;
CLLocation*当前位置;
}
+(位置控制器*)共享状态;
-(无效)开始;
-(无效)停止;
-(BOOL)位置已知;
@属性(非原子,保留)CLLocation*currentLocation;
@结束
@实现位置控制器
@综合当前位置;
静态定位控制器*sharedInstance;
+(位置控制器*)共享状态{
@同步(自){
如果(!sharedInstance)
sharedInstance=[[LocationController alloc]init];
}
返回共享状态;
}
+(id)alloc{
@同步(自){
NSAssert(sharedInstance==nil,@“试图分配singleton LocationController的第二个实例”);
sharedInstance=[super alloc];
}
返回共享状态;
}
-(id)init{
if(self=[super init]){
self.currentLocation=[[CLLocation alloc]init];
locationManager=[[CLLocationManager alloc]init];
locationManager.delegate=self;
[自启动];
}
回归自我;
}
-(无效)开始{
[locationManager startUpdatingLocation];
}
-(无效)停止{
[locationManager停止更新位置];
}
-(BOOL)位置已知{
if(round(currentLocation.speed)=-1)返回否;否则返回是;
}
-(void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation{
//如果从核心位置返回的时间间隔超过两分钟,我们将忽略它,因为它可能来自旧会话
如果(abs([newLocation.timestamp-timeIntervalSinceDate:[NSDate-date]])<120{
self.currentLocation=新位置;
}
}
-(无效)locationManager:(CLLocationManager*)manager错误:(N错误*)错误{
UIAlertView*警报;
alert=[[UIAlertView alloc]initWithTitle:@“错误”消息:[错误描述]委托:nil CancelButtontile:@“确定”其他Buttontiles:nil];
[警报显示];
[警报发布];
}
-(无效)解除锁定{
[locationManager发布];
[当前位置释放];
[super dealoc];
}
@结束
没有这样的便利,你不应该创建自己的。在像iPhone这样的设备上,“阻塞直到得到结果”是极其糟糕的编程实践。检索位置可能需要几秒钟;你永远不应该让你的用户那样等待,代表们也要确保他们不会那样等待。我很感激布拉德·史密斯的回答。在实现它时,我发现他使用的其中一种方法在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];
}
-(无效)位置管理器:(CLLocationManager*)管理器更新位置:(NSArray*)位置{
如果(abs([[locations lastObject]timeIntervalSinceDate:[NSDate date]])<120){
[self-setCurrentLocation:[locations lastObject]];
}
}
//与iOS5的向后兼容性。
-(void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation{
NSArray*locations=[NSArray arrayWithObjects:oldLocation,newLocation,nil];
[self locationManager:manager didUpdateLocations:locations];
}
我简化并组合了多个答案,其中位置只有在有效时才会更新
它也可以在OSX和iOS下工作
这假设用户突然需要当前位置的用例。在本例中,如果时间超过100毫秒,则视为错误。(假设GPS IC和| Wifi(苹果的Skyhook克隆)已经启动,并且已经有了很好的修复。)
你应该澄清这个问题:如果你知道如何使用CLLocationManager,那么实施这种“方便方法”有什么问题?我认为问题在于它不是那么容易。通常它首先返回一个旧的位置,然后是一个非常不准确的位置,然后是逐渐更好的位置,在什么时候你决定你拥有你想要的位置?这真的取决于你。线程,是的,当与完成时的回调相结合时。其中,回调被安排在原始运行循环上。这将为您提供一个与CLLocationManager的委托完全相同的接口。在终端用户应用程序中,“阻止直到完成”从来都不是一个好的设计。我不同意,“阻止直到完成”在各种应用程序中有许多合法的用途,并且不是“冻结UI直到完成”的同义词。试图使一切都异步只会导致奇怪的行为和错误的应用程序。谁会在乎UI显示/响应的速度有多快
#import "LocationManager.h"
// wait up to 100 ms
CLLocation *location = [LocationManager currentLocationByWaitingUpToMilliseconds:100];
if (!location) {
NSLog(@"no location :(");
return;
}
// location is good, yay