Завершение выборки местоположения в рамках «потяните, чтобы обновить»?

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

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

У меня есть свойство, которое содержит текущее местоположение пользователей. Можно ли «удерживать» до тех пор, пока это свойство не станет равным нулю (т. е. местоположение не будет установлено) перед вызовом обновления для вызова «showMap», возможно, если он не может найти пользователя после установленного времени, он просто выдает ошибку ? Я попытался использовать цикл while, чтобы постоянно проверять свойство currentLocation, но это не казалось правильным и в любом случае не работало.

Это мой код обновления, который настроен в viewDidLoad:

__typeof (&*self) __weak weakSelf = self;

[self.scrollView addPullToRefreshWithActionHandler:^ {
    int64_t delayInSeconds = 1.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [weakSelf showMap];
    });
}];

Когда используется запрос на обновление, он вызывает следующие методы:

- (void)showMap
{
    [self.locationManager updateCurrentLocation];

    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(finishRefresh) userInfo:nil repeats:NO];

}

- (void)finishRefresh
{
    [self.scrollView.pullToRefreshController didFinishRefresh];

    [self performSegueWithIdentifier:@"showMap" sender:self];
}

person Ash R    schedule 16.10.2013    source источник


Ответы (1)


Абстрактный

Чтобы избежать преждевременного отображения карты, вы должны фактически дождаться операции асинхронного обновления, и самым чистым шаблоном для этого будет делегирование. Вот хороший документ Apple на его применение в Cocoa/Cocoa Touch.

Тогда это будет работать примерно так:

  1. Pull-to-Refresh запускает обновление местоположения.
  2. Когда обновление местоположения завершено, locationManager уведомляет ваш контроллер, и контроллер представляет карту.

Как это сделать

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

CLLocationManager имеет свойство делегата. Ваш контроллер представления должен:

  1. соответствовать Протокол CLLocationManagerDelegate
  2. добавить себя в качестве делегата в locationManager
  3. реализовать метод locationManager:didUpdateLocations: — он вызывается, когда данные о местоположении получены и готовы к использованию.

Реализация этого метода должна выглядеть примерно так:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 
{
    /*
     *  shouldShowMap — BOOL property of View Controller, actually optional 
     *  but allowing to filter out handling of unwanted location updates 
     *  so they will not trigger map segue every time
     */
    if (self.shouldShowMap) {
        [self performSegueWithIdentifier:@"showMap" sender:self];
        self.shouldShowMap = NO; 
    }
    // stop updating location — you need only one update, not a stream of consecutive updates
    [self.locationManager stopUpdatingLocation];
}

Ваш обработчик Pull-to-Refresh должен выглядеть так:

__typeof (&*self) __weak weakSelf = self;

[self.scrollView addPullToRefreshWithActionHandler:^ {
    self.shouldShowMap = YES;
    [weakSelf.locationManager startUpdatingLocation];
}];

Надеюсь, это немного помогло. Лучший способ узнать (ну, в большинстве случаев) — посмотреть, как вещи реализованы в системных фреймворках. Подумайте в этом направлении, и вы обязательно найдете решение :)

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

person ivanmoskalev    schedule 16.10.2013
comment
Вау, отличный ответ Иван. Мой класс диспетчера местоположений — это пользовательский класс, который использует CLLocationManager, и обновления didUpdateLocation: доставляются в этот класс. Я думаю, мне нужно немного изменить его структуру, чтобы обновления доставлялись на мой контроллер, чтобы он знал, когда представлять карту. Я пойду с вашим советом позже сегодня. - person Ash R; 17.10.2013
comment
Просто чтобы вернуться и сообщить, что это сработало отлично. Спасибо за вашу помощь с указанием меня в правильном направлении. - person Ash R; 17.10.2013
comment
Рад, что это помогло вам! Удачи с вашим приложением и удачного кодирования :) - person ivanmoskalev; 17.10.2013