Как использовать делегат с завершенной загрузкой MKMapView, возможно ли делегировать "завершенный показ"?

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

Это то, что я делаю после сохранения пользовательских кратковременных нажатий:

  • Установите bool "save" в true
  • Центрировать и увеличить масштаб аннотации (без анимации)
  • Когда вызывается метод делегирования mapViewDidFinishLoadingMap, и если сохранение верно:
  • Создайте UIImage из представления и сохраните его. Отклонить модальный вид.

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

Gridlines unfinished

Мой вопрос в том, как я могу обеспечить завершение загрузки карты и законченное отображение, прежде чем сохранить этот значок?

Ответ 1

Обновление: iOS7 имеет новый делегат, который, возможно, устранил эту проблему. Я еще не подтвердил, так или иначе.

- (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered 

Поддержка Pre iOS6:

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

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

Если mapViewDidFinishLoadingMap будет вызван reset таймер снова в течение 2 секунд в будущем. Когда таймер, наконец, погаснет, получите снимок карты, и это должно быть правильно.

Вы также захотите рассмотреть другие обратные вызовы, такие как mapViewDidFailLoadingMap. Также проверьте это на шумном соединении, так как 2 секунды могут быть недостаточно длинными, если для получения фрагментов требуется много времени.

- (void)restartTimer
{
    [self.finishLoadingTimer invalidate];
    self.finishLoadingTimer = [NSTimer scheduledTimerWithTimeInterval:2.0
                                                               target:self
                                                             selector:@selector(mapLoadingIsFinished)
                                                             userInfo:nil
                                                              repeats:NO];
}

- (void)userClickedSave
{
    assert(self.saving == NO);
    if (self.saving == NO) {
        self.saving = YES;
        assert(self.finishLoadingTimer == nil);
        self.view.userInteractionEnabled = NO;
        [self restartTimer];
    }
}

- (void)mapLoadingIsFinished
{
    self.finishLoadingTimer = nil;
    [self doSnapshotSequence];
    self.saving = NO;
    self.view.userInteractionEnabled = YES;
}

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
    if (self.saving) {
        [self restartTimer];
    }
}

Ответ 2

При разработке для iOS7 лучшим делегатом для использования является: mapViewDidFinishRenderingMap: fullRendered:

mapViewDidFinishRenderingMap:fullyRendered

Ответ 3

Вы уверены, что область, где вы снимаете скриншот, поддерживает уровень масштабирования, который вы применяете. Например, в США поддержка уровня увеличения выше, вы можете увеличить масштаб до максимальной детали, в то время как в Азии может быть высокий уровень масштабирования, возможно, не поддерживается.