Оптимизация CLLocationManager / CoreLocation для более быстрого извлечения точек данных на iPhone
в настоящее время я использую CoreLocation + CLLocationManager для сравнения текущего местоположения пользователей с количеством других местоположений. Проблема, с которой я сталкиваюсь, заключается в том, что я имею дело с городскими районами, где местоположения близки друг к другу, поэтому мне нужно указать местоположение пользователя так точно, как позволяет устройство, не жертвуя слишком много времени. Мои расчеты чертовски точны, проблема в том, что сбор 10 образцов занимает слишком много времени. Я вставлю свои фильтры / соответствующий код точности под. Если кто-нибудь может прокомментировать, как я могу ускорить это, это было бы здорово. Пока я не ускорю его, это довольно бесполезно в моем приложении, поскольку в настоящее время требуется около 3-4 минут для сбора информации, продолжительность, которая не принимается моей целевой демографией.
код выглядит так:
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if (newLocation.horizontalAccuracy > 0.0f &&
newLocation.horizontalAccuracy < 120.0f) { // roughly an accuracy of 120 meters, we can adjust this.
[myLocs addObject:newLocation];
}
Спасибо за любые трюки оптимизации, чтобы ускорить это.
3 ответов
у меня также было много проблем с CLLocationManager на iPhone. Из разных приложений, а также проб и ошибок это то, что я понял;
1) Используйте одноэлементный класс для locationManager, только один экземпляр, следуйте примерам в:
пример LocateMe от Apple
Tweetero:http://tweetero.googlecode.com/svn/trunk
Я думаю, что вы можете иметь только один менеджер местоположения работает, есть только один чип GPS в таким образом, если вы запустите несколько объектов диспетчера местоположения, они будут конфликтовать, и вы получите ошибки от диспетчера местоположения GPS, заявив, что он не может обновляться.
2) Будьте предельно осторожны, как вы обновите locationManager.desiredAccuracy
и
locationManager.distanceFilter
следуйте примеру в коде Apple для этого в FlipsideViewController:
[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;
этот подход работает и не вызывает ошибок. Если вы обновите desiredAccuracy или distanceFilter в главном делегате петля:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Core Location, вероятно, пожалуется, что он не может обновить значения и дать вам ошибки.
Кроме того, используйте только константы для desiredAccuracy
поставляется Apple, и не другие,
таким образом;
kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers
использование других значений может дать вам ошибки с locationManager.
Для distanceFilter
вы можете использовать любое значение, но имейте в виду, что люди заявили, что у него есть проблемы,
основное значение по умолчанию: -1 = Best, я использовал 10.0, и это кажется ОК.
3) чтобы заставить новое обновление, вызовите startUpdates
метод, как в Tweetero, это заставляет
locationManager, чтобы сделать это, и он должен попытаться получить вам новое значение.
4) основная процедура делегата местоположения сложно получить точные обновления из. Когда приложение впервые инициализирует вы можете быть в точности 1000 метров или больше, таким образом одна попытка не поможет. Три попытки после инициализации обычно получают вас в пределах 47 или около того метров, что хорошо. Помните, что каждая последующая попытка будет дольше и дольше, чтобы улучшить вашу точность, таким образом, он становится дорогим быстро. Это то, что вам нужно сделать: Принимать новое значение только в том случае, если оно Если новое местоположение имеет немного лучшую точность, возьмите новое местоположение или Если новое положение имеет точность
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
locationDenied = NO;
if(![[NSUserDefaults standardUserDefaults] boolForKey:@"UseLocations"])
{
[self stopAllUpdates];
return;
}
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = abs([eventDate timeIntervalSinceNow]);
attempts++;
if((newLocation.coordinate.latitude != oldLocation.coordinate.latitude) && (newLocation.coordinate.longitude != oldLocation.coordinate.longitude))
locationChanged = YES;
else
locationChanged = NO;
#ifdef __i386__
//Do this for the simulator since location always returns Cupertino
if (howRecent < 5.0)
#else
// Here's the theory of operation
// If the value is recent AND
// If the new location has slightly better accuracy take the new location OR
// If the new location has an accuracy < 50 meters take the new location OR
// If the attempts is maxed (3 -5) AND the accuracy < 150 AND the location has changed, then this must be a new location and the device moved
// so take this new value even though it's accuracy might be worse
if ((howRecent < 5.0) && ( (newLocation.horizontalAccuracy < (oldLocation.horizontalAccuracy - 10.0)) || (newLocation.horizontalAccuracy < 50.0)
|| ((attempts >= attempt) && (newLocation.horizontalAccuracy <= 150.0) && locationChanged)))
#endif
{
attempts = 0;
latitude = newLocation.coordinate.latitude;
longitude = newLocation.coordinate.longitude;
[currentLocation release];
currentLocation = [newLocation retain];
goodLocation = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateLocationNotification" object: nil];
if (oldLocation != nil) {
distanceMoved = [newLocation getDistanceFrom:oldLocation];
currentSpeed = newLocation.speed;
distanceTimeDelta = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
}
}
// Send the update to our delegate
[self.delegate newLocationUpdate:currentLocation];
}
если у вас есть iPhone 3GS получать обновления заголовков намного проще, вот код в том же модуле, что и выше:
//This is the Heading or Compass values
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
if (newHeading.headingAccuracy > 0)
{
[newHeading retain];
// headingType = YES for True North or NO for Magnetic North
if(headingType) {
currentHeading = newHeading.trueHeading;
} else {
currentHeading = newHeading.magneticHeading;
}
goodHeading = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateHeadingNotification" object: nil];
}
}
Надежда это помогает людям!
didupdatetolocation обновляется только тогда, когда пользователь перемещает местоположение. Это может быть спорадическим, как вы наверняка заметили. CCLocationManager не отправляет регулярные обновления, а вместо этого отправляет обновления, когда пользователь переместился, или увеличивает его точность. Когда я неподвижен и запускаю приложение, я обычно получаю около трех обновлений, а затем ничего на некоторое время. Google Maps делает аналогичную вещь, показывая кольцо против точки по мере увеличения точности. Я бы посоветовал подождать, пока ты не доберешься. требуемая точность (
Если вы привыкли к "нормальному" GPS, где отправляются обновления, и он продолжает уточнять его точность, я боюсь, что iPhone не предназначен для этого.
кроме того, вы можете использовать API MapKit и показать пользователю карту с их местоположением и позволить "принять", как только они почувствуют, что местоположение достаточно точное. Я замечаю, что иногда я получаю точку, а затем 30 секунд спустя перемещает меня, возможно, на 50 метров ближе к тому, где я на самом деле.
Я написал git repo на этом, который вы можете использовать https://github.com/xelvenone/M6GPSLocationManager
- если точность результата лучше, чем acceptableAccuracy, мы сделали
- если мы получим обновление о occuracy, мы ждем maximumWaitTimeForBetterResult, чтобы получить лучший, - если этого не произойдет, мы закончим и возьмем лучший
- если мы постоянно получаем обновления, которые превышают maximumAttempts, мы берем лучший (вероятно, мы все равно движемся)
- если мы не получим никакого другого обновления через 30 секунд, мы закончили (вероятно, не будет никакого другого обновления)
код
- (void)scopeToCurrentLocationWithAcceptableAccuracy:(CLLocationAccuracy)acceptableAccuracy
maximumWaitTimeForBetterResult:(NSTimeInterval)maximumWaitTimeForBetterResult
maximumAttempts:(NSInteger)maximumAttempts
onCompletion:(M6GPSLocationManagerCompletion)completion;