Принудительное обновление местоположения - PullRequest
2 голосов
/ 16 августа 2011

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

Я хотел бы убедиться, что у меня есть новое новое местоположение.

Что не так с этим кодом?

double aa,bb,cc;

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    [manager stopUpdatingLocation]; //only stop if new reliable pos fetched.
        //old data? retry.
    aa=[newLocation.timestamp timeIntervalSinceReferenceDate];
    bb=[NSDate timeIntervalSinceReferenceDate];
    cc=bb-aa;   //must be <60 - minute-fresh
    if (cc>60) {
        [manager stopUpdatingLocation]; //only stop if new reliable pos fetched.
        [manager startUpdatingLocation];    //only stop if new reliable pos fetched.
        return;
    }
...handle position
}

Симптомы состоят в том, что при запуске приложения cc составляет около 1200 секунд, затем при каждой повторной попытке оно увеличивается на несколько секунд.

Я пробовал -[newLocation.timestamp timeIntervalSinceNow], и аналогично он увеличивается на несколько секунд при каждой повторной попытке. В какой-то момент интервал был ~ 2400.

Я использую FilterNone и AccuracyBest, если это может повлиять на это.

Я открыт для альтернативных решений кода, чтобы убедиться, что у вас есть свежая позиция.

Ответы [ 3 ]

2 голосов
/ 18 августа 2011

Ответ состоял в том, что вам нужно написать обработчик так, как вы хотите, чтобы он вел себя.

Я прочитал об этой распространенной проблеме.Я должен был уточнить, что «сила» означает , чтобы начать однозначное поведение, которое дает надежную позицию при оптимальных условиях для телефона.Не занят - ждать, пока не будет выполнено, или ожидать немедленного результата / кода ошибки.

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

Почему мне вообще нужно было спросить об этом:

  1. не существует метода, функционирующего как описано выше

  2. с использованием кода из книги (More Iphone 3 Development)

  3. принаписав его с нуля (глядя на LocateMe.xproj), обнаружив, что:

  4. поведение симулятора отличается от поведения телефона (не говоря уже о самой позиции, которая, очевидно, так же хороша, как и поиск по ipсделать это, но поведение didUpdateToLocation).Признавая ограничения симулятора, метод должен, по крайней мере, вести себя как на устройстве.Но в настоящее время правильно написанный код обработки / проверки местоположения просто теряет время ожидания в симуляторе (как в примере LocateMe), в то время как неправильный код (запрашивая один раз и используя newLocation при обратном вызове) работает.

  5. и ошибка, приводившая к тому, что didUpdateToLocation вызывался дважды после [locationManager stopUpdatingLocation];

Если в дополнение к этому вы (как и я) загружаете данные, основанные на вашей позиции, и данные требуются для несколькихПо мнению вашего приложения, поведение методов извлечения местоположения Apple не позволяет легко обрабатывать цепочку обновления-загрузки-вычисления-присутствия последовательно и без проблем во всем приложении.Особенно, если вы застряли между восприятием пользователя / босса или решением о том, как оно должно работать (скала) и как работает система (трудное место).

Вот мой текущий код, который работает на устройстве ив симуляторе:

//ask for a position, as fresh as possible.
-(void)updateMeMap {
    lastloc.coordinate=homeloc.coordinate;
    lm.delegate=self;
    ctr=0;
    [self performSelector:@selector(stopUpd) withObject:nil afterDelay:gpstimeout];
    [lm startUpdatingLocation];
}

//called on each position update.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    ctr++;
    if (ctr<15) {
        NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
        NSLog(@"%d",ctr);
        if (locationAge<60) {
            NSLog(@"Found");
            ctr=40;
            homeloc.coordinate=newLocation.coordinate;
            [self stopUpd];
            [self reload];
        } else {
            NSLog(@"Lastupd");
            lastloc.coordinate=newLocation.coordinate;
        }
    } else {
            //enough tries, if not canceled choose lastloc.
        if (ctr<40) {
            NSLog(@"Last");
            ctr=40;
            homeloc.coordinate=lastloc.coordinate;  
            [self stopUpd];
            [self reload];
        }
    }
}

//force stop updates. ctr prevents extra calls after stopUpdatingLocation.
//called after the timeout delay, if position found, cancel the timeout.
-(void)stopUpd {
    [lm stopUpdatingLocation];
    lm.delegate=nil;
    if (ctr<15) {
        ctr=40; //2 extra calls after stopupda... otherwise, now do nothing.
        NSLog(@"Timeout");
        homeloc.coordinate=lastloc.coordinate;  //@need "copy"?
        [self reload];
    } else {
        ctr=40; //2 extra calls after stopupda... otherwise, now do nothing.
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpd) object:nil];
    }
}

    // "couldn't get userlocation" handler. I also cancel like this on connectionDidFailWithError.
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"Location failed: %@",[error localizedDescription]);
    ctr=0;
    [self stopUpd];
}

Там, где есть ctr для предотвращения 2 дополнительных вызовов, lastloc - последняя известная надежная позиция, homeloc - позиция телефона, используемая для (поточной) загрузки данных, специфичных для местоположенияс [перезагрузить себя].

Константы 15 и 60 являются безопасными значениями из реальных испытаний;gpstimeout установлен на 30. Если вы много работаете в симуляторе, вы можете установить его на что-то короткое, например, на 3 секунды, поскольку все, что вы получите, это устаревшая, но относительно полезная позиция, и не более до истечения времени ожидания.

Редактировать: Если вы можете улучшить мой код или указать на упущение, я отмечу это как ответ, я ненавижу отмечать мой собственный как ответ.

1 голос
/ 16 августа 2011

Что если вы добавите больше кода в проверку возраста, например:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
    if (locationAge<60) {
        [manager stopUpdatingLocation]; //only stop if new reliable pos fetched.
     ...handle position
    }
}
1 голос
/ 16 августа 2011

Я столкнулся с похожей проблемой в одном из моих предыдущих приложений.

Насколько мне известно, нет способа принудительно обновить местоположение - (я долго искал и ничего не нашел)

Одна вещь, которую я обнаружил, - это использование клавиши UIBackgroundModes в моем info.plist.

Поддержка некоторых типов фонового выполнения должна быть заранее объявлена ​​приложением, которое их использует. Приложение заявляет об этой поддержке, включив ключ UIBackgroundModes в свой файл Info.plist. Его значение является массивом, который содержит одну или несколько строк со следующими значениями:

  • аудио. Приложение воспроизводит звуковой контент для пользователя, находясь в фон. (Это включает в себя потоковое аудио или видео с использованием AirPlay.)
  • location. Приложение держит пользователей в курсе их местоположение, даже когда работает в фоновом режиме.
  • VoIP. Приложение предоставляет пользователю возможность совершать телефонные звонки, используя Интернет-соединение.

Что вы ищете? См. документы для получения дополнительной информации.

...