CLLocationManager를 사용하는 방법을 이미 알고 있으므로 대리인을 비롯한 모든 사람들이 힘들게 할 수 있습니다.iPhone의 현재 위치를 가져 오는 가장 쉬운 방법은 무엇입니까?
하지만 지금까지 한 번만 현재 위치를 얻는 편리한 방법을 원합니다. 그리고 결과를 얻을 때까지 차단합니다.
CLLocationManager를 사용하는 방법을 이미 알고 있으므로 대리인을 비롯한 모든 사람들이 힘들게 할 수 있습니다.iPhone의 현재 위치를 가져 오는 가장 쉬운 방법은 무엇입니까?
하지만 지금까지 한 번만 현재 위치를 얻는 편리한 방법을 원합니다. 그리고 결과를 얻을 때까지 차단합니다.
직접 코드를 작성하지 않으면 "편리한 방법"이 없지만 "편리한"사용자 지정 코드로 위임 메서드를 구현해야합니다.
델리게이트 패턴은 이유가 있으며, 델리게이트는 Objective-C의 큰 부분이므로, 익숙해 지길 권한다.
내가하는 일은 코어 위치에서 업데이트를 관리하는 싱글 톤 클래스를 구현하는 것입니다. 이미 지적 된 바와 같이, 메인 스레드를 차단하는 것은 아마 아닙니다,
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
}
그러나 내 현재 위치를 액세스하려면, 당신은 당신이 이런 일을 할 수있는 메인 스레드를 차단하고 싶었 경우 CLLocation *myLocation = [[LocationManager sharedInstance] currentLocation];
할 좋은 생각이긴하지만, 뭔가를 짓고있는 시점에서 좋은 점프가 될 수 있습니다. 또한 내가 작성한 클래스가 위치 업데이트에 대한 타임 스탬프를 확인하고 오래된 위치는 무시하므로 코어 위치에서 부실 데이터를 가져 오는 문제를 방지 할 수 있습니다.
이것은 내가 작성한 싱글 톤 클래스입니다. 가장자리 주위가 약간 거친 점에 유의하십시오.
#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
이 솔루션을 이용해 주셔서 감사합니다. 그것은 사용할 수있는 좋은 작은 컨트롤러입니다.내가 찾은 한 가지는 locationKnown 메소드가 정확하지 않다는 것입니다. 즉, currentLocation이 init 메소드에서 초기화되었으므로 항상 YES를 반환했습니다. 다음은 speed 속성을 사용하여 사용자 위치 수신 여부를 결정하는 메서드의 다른 버전입니다. - (BOOL) locationKnown { if (round (currentLocation.speed) == -1) return NO; else return 예; } –
코드를 편집했습니다. 올바르게 이해했으면합니다. –
리소스를 할당했지만 배포하지 않았습니다. 당신은 어떤 문제를 일으키지 않을 것이라고 당신이 어디에서 풀어 줄 것인지 말해 주시겠습니까? –
그런 편의가 없으므로 직접 작성해서는 안됩니다. "결과가 나올 때까지 차단"은 입니다. iPhone과 같은 기기의 프로그래밍 연습은 극히 불량합니다 (). 위치를 검색하는 데 몇 초가 걸릴 수 있습니다. 사용자가 그런 식으로 기다리게해서는 안되며, 위임자는 사용자가 기다리지 않도록해야합니다.
그게 무슨 스레드가 아닌가요? –
완료시 콜백과 결합 된 스레드 (예)입니다. 콜백은 원래 실행 루프에서 예약됩니다. 어느 CLLocationManager의 델리게이트 (delegate)와 같은 인터페이스를 제공합니다. "Block until done"은 최종 사용자 앱에서는 좋은 디자인이 아닙니다. –
나는 "완료 될 때까지 차단"은 모든 종류의 앱에서 많은 합법적 인 사용을하고 있으며, "완료 될 때까지 UI가 멈추는"것과 동의어가 아닙니다. * 모든 것을 * 비동기로 만들려고하면 기괴한 행동과 버그가있는 앱으로 이어집니다. UI가 얼마나 빨리 표시되는지/표시해야하는 정보가 아직 제공되지 않는 경우 누가 응답합니까? 비동기 작업이 자리를 잡으므로 비동기 작업도 차단됩니다. 하나가 좋고 다른 하나가 나쁘지 않은 경우는 아닙니다. – aroth
나는 Brad Smith의 대답을 높이 평가했다. 이를 구현하면서 그가 사용하는 방법 중 하나는 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];
}
나는 간단하고 유효하다면 위치 만 업데이트되는 경우 여러 답변을 결합했다.
OSX 및 iOS에서도 작동합니다.
여기서는 사용자가 현재 위치를 갑자기 원하는 경우를 가정합니다. 이 예제에서 100ms 이상 걸리면 오류로 간주됩니다. 당신이 CLLocationManager를 사용하는 방법을 알고있는 경우 : -
#import "LocationManager.h"
// wait up to 100 ms
CLLocation *location = [LocationManager currentLocationByWaitingUpToMilliseconds:100];
if (!location) {
NSLog(@"no location :(");
return;
}
// location is good, yay
당신은 질문을 명확히해야한다
잘 작동합니다! –
| (이미 와이파이 (애플의 스카이 훅 클론)가 이미 해고되고 좋은 수정이있는 GPS IC &가 가정합니다.) 그런 "편의 방법"을 구현하는 데있어 어떤 문제가 있습니까? – tcurdt
나는 문제가 그렇게 쉽지 않다고 생각한다. 일반적으로 그것은 오래된 위치를 먼저 반환하고, 격렬하게 무적 인 것을 뒤 따르고, 점진적으로 더 좋은 것을 뒤 따르는데, 어느 시점에서 원하는 위치를 찾았습니까? 그것은 당신에게 달려 있습니다. – rustyshelf
좋은 지적, 녹슨! –