2009-01-19 155 views
22

我已經知道如何使用CLLocationManager,所以我可以用困難的方式來完成,包括委託和所有這些。獲取iPhone當前位置的最簡單方法是什麼?

但我想有一個方便的方法,僅僅獲得當前位置,一次,阻塞,直到它得到的結果。

+0

你應該澄清一個問題:如果你知道如何使用CLLocationManager - 實施這種「便利方法」的問題是什麼? – tcurdt 2009-01-20 00:04:51

+10

我認爲問題並不那麼容易。通常情況下,它首先會返回一箇舊的位置,然後是一個非常不尋常的位置,然後是逐漸變好的位置,在什麼時候您決定擁有一個您想要的位置?這真的取決於你。 – rustyshelf 2009-01-20 00:42:21

+0

好點,生鏽! – 2009-01-20 14:18:57

回答

4

有沒有「方便的方法」除非你自己編寫它們,但你仍然需要實現在任何自定義代碼,你用它來把事情委託方法「方便」。

的委託模式是有原因的,並作爲代表是Objective-C的重要組成部分,我建議你與他們舒服。

45

我所做的是實現一個單例類來管理來自核心位置的更新。要訪問我的當前位置,我做了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 
+0

感謝您的解決方案。這是一個很好的小控制器。我發現的一件事是,locationKnown方法不是很準確 - 它總是返回YES,因爲currentLocation在init方法中初始化。以下是使用speed屬性確定用戶位置是否已被接收的方法的替代版本: - (BOOL)locationKnown if(round(currentLocation.speed)== -1) return NO; else return YES; } – 2010-08-13 00:25:21

7

有沒有這樣的便利,你不應該創建自己的。 「阻塞直到得到結果」爲極其糟糕在像iPhone這樣的設備上進行編程練習。檢索一個位置可能需要幾秒鐘的時間;你永遠不應該讓你的用戶這樣等待,而且代表確保他們不這樣做。

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

我簡化和合並多個答案的地方,如果它是有效的位置,纔會更新。

它也適用於OSX以及iOS。

這裏假定當前位置突然被用戶所需的用例。如果在這個例子中超過100毫秒,它被認爲是一個錯誤。 (假設GPS IC & |無線上網(蘋果公司的天棚克隆)已經被解僱了,並具有良好的修復了。)

#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

相關問題