Подтвердить что ты не робот

Какой самый простой способ получить текущее местоположение iPhone?

Я уже знаю, как использовать CLLocationManager, поэтому я мог бы сделать это с большим трудом, с делегатами и всем этим.

Но я бы хотел иметь удобный метод, который просто получает текущее местоположение, один раз и блокирует до получения результата.

4b9b3361

Ответ 1

Что я делаю, так это реализовать одноэлементный класс для управления обновлениями из основного местоположения. Чтобы получить доступ к моему текущему местоположению, я делаю 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

Ответ 2

Нет такого удобства, и вы не должны создавать свои собственные. "Блокирует до получения результата" - это крайне плохая практика программирования на устройстве, таком как iPhone. Для получения местоположения может потребоваться несколько секунд; вы никогда не должны заставлять своих пользователей так ждать, и делегаты не гарантируют, что они этого не делают.

Ответ 3

Нет "удобных методов", если вы сами не закодируете их, но вам все равно нужно реализовать методы делегирования в любом пользовательском коде, который вы используете, чтобы сделать вещи "удобными".

У шаблона делегата есть причина, и поскольку делегаты являются большой частью Objective-C, я рекомендую вам с ними комфортно.

Ответ 4

Я оценил ответ Брэда Смита. Внедряя это, я обнаружил, что один из методов, которые он использует, устарел с 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];
}

Ответ 5

Я упростил и объединил несколько ответов на вопрос, где местоположение обновляется только в том случае, если оно действительно.

Он также работает под OSX, а также с iOS.

Это предполагает прецедент, когда пользователь хочет, чтобы текущее местоположение неожиданно стало желательным. Если в этом примере он принимает более 100 мс, он считает ошибку. (Предполагается, что IC 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