Оптимизация CLLocationManager/CoreLocation для получения точек данных быстрее на iPhone

Свифт 3

tableView.setContentOffset(CGPoint.zero, animated: true)

, если tableView.setContentOffset не работает.

Использование:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()
17
задан 4 July 2009 в 00:52
поделиться

2 ответа

I've had lots of issues with CLLocationManager on the iPhone also. Я понял это из разных приложений, методом проб и ошибок;

1) Используйте одноэлементный класс для locationManager, ТОЛЬКО ОДИН экземпляр, следуйте примерам в:

Пример LocateMe от Apple

Tweetero: http://tweetero.googlecode.com/svn/trunk

Я думаю, у вас может быть запущен только один диспетчер местоположения, в iPhone только один чип GPS, поэтому, если вы запустите несколько объектов диспетчера местоположения, они возникнет конфликт, и вы получите сообщение об ошибке от диспетчера местоположения GPS о невозможности обновления.

2) Будьте предельно осторожны при обновлении locationManager.desiredAccuracy и locationManager.distanceFilter

Следуйте примеру из кода Apple для этого в FlipsideViewController:

[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;

Этот подход работает и не вызывает ошибок. Если вы обновите желаемую точность или distanceFilter в основном цикле делегата:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation  fromLocation:(CLLocation *)oldLocation

Core Location, скорее всего, будет жаловаться на то, что не может обновить значения, и выдаст вам ошибки. Кроме того, используйте только константы для желаемой точности , предоставленные Apple, и никакие другие, таким образом;

kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometer

Использование других значений может привести к ошибкам из locationManager. Для distanceFilter вы можете использовать любое значение, но имейте в виду, что люди заявляют, что у него есть проблемы, основное значение по умолчанию: -1 = Best, я использовал 10.0, и вроде нормально.

3) Чтобы принудительно выполнить новое обновление, вызовите метод startUpdates , как в Tweetero, это заставит locationManager, и он должен попытаться дать вам новое значение.

4) Из основной процедуры делегирования местоположения сложно получить точные обновления. Когда ваше приложение впервые инициализируется, вы можете отклониться от точности на 1000 метров или более, поэтому с одной попытки этого не сделать. Обычно три попытки после инициализации с точностью до 47 метров, что хорошо. Помните, что каждая последующая попытка требуется все больше и больше времени для повышения вашей точности, поэтому он быстро становится дорогим. Вот что вам нужно сделать: Возьмите новое значение, только если оно недавнее И Если новое местоположение имеет немного лучшую точность, выберите новое местоположение ИЛИ Если новое местоположение имеет точность <50 метров, выберите новое местоположение ИЛИ Если количество попыток превышает 3 или 5 И точность <150 метров И местоположение ИЗМЕНИЛОСЬ, значит это новое местоположение и устройство переехало, возьмите это значение, даже если точность хуже. Вот мой код местоположения для этого:

- (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];

    }
}

Надеюсь, это поможет людям!

48
ответ дан 30 November 2019 в 10:36
поделиться

didUpdateToLocation обновляется только тогда, когда пользователь перемещает местоположение. Это может быть спорадическим, как я уверен, вы заметили. CCLocationManager не отправляет регулярные обновления, а вместо этого отправляет обновления, когда пользователь перемещается, или это повышает точность. Когда я неподвижен и запускаю приложение, я обычно получаю около трех обновлений, а потом какое-то время ничего. Google Maps делает то же самое, показывая кольцо против точки по мере увеличения точности. Я бы посоветовал подождать, пока вы не достигнете требуемой точности (<120.0f), а затем выполнить свои действия или вычисления.

Если вы привыкли к «нормальному» GPS, на который отправляются обновления, а он продолжает уточните его точность, боюсь, iPhone не предназначен для этого.

В качестве альтернативы вы можете использовать API MapKit, и показать пользователю карту с его местоположением и позволить пользователю «принять», как только он почувствует, что местоположение достаточно точное. Иногда я замечаю, что получаю точечный объект, а затем через 30 секунд он перемещает меня, может быть, на 50 метров ближе к тому месту, где я нахожусь.

4
ответ дан 30 November 2019 в 10:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: