Создание iOS-приложения: карты Apple vs OpenStreetMaps

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

Недостатки встроенных карт от Apple

Кто только не ругал Apple за то, что они в последних версиях iOS заменили проверенные временем карты Google на собственный сервис. Ругали как за множественные неточности и ляпы, так и за низкую детализацию карт. И если с того времени какие-то ошибки были исправлены, то для многих стран отличных от США или стран Западной Европы проблема детализации до сих пор остается актуальной. Например, в России даже в Москве по данным Apple нет домов, а некоторые города и вовсе выглядят как несколько пересекающихся дорог среди полей.

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

Альтернатива: OpenStreetMap

OpenStreetMap – открытый проект, целью которого является создание подробной свободной и бесплатной карты мира. Проект непрерывно пополняется и развивается силами участников-добровольцев по всему миру.  Внести изменения и дополнения в карту может любой зарегистрированный участник. За счет этого обеспечивается очень высокая точность и подробность картографических данных. Давайте сравним, как выглядят известные города на картах Apple и OpenStreetMap.

г. Пхеньян, Северная Корея

Пхеньян, Северная Корея, на картах Apple

карты Apple

Пхеньян, Северная Корея, на картах OSM

OSM

Вашингтон, США

Вашингтон, США, на картах Apple

карты Apple

Вашингтон, США, на картах OSM

OSM

г. Барнаул, Россия

<Барнаул, РФ, на картах Apple

карты Apple

Барнаул, РФ, на картах OSM

OSM

Думаю, ни у кого не возникнет сомнений в преимуществе OSM по детализации карт. Рассмотрим как мы можем воспользоваться ими в своих приложениях.

Использование карт OSM при создании iOS приложений

Подключить карты OSM в свой проект можно несколькими способами. Мы рассмотрим подключение и использование карт с помощью MapBox iOS SDK. MapBox iOS SDK – это набор инструментов для создания картографических iOS-приложений. Работа с ним напоминает работу со стандартным фреймворком MapKit, но отличается гораздо большей гибкостью в плане визуализации, кастомизации и оффлайн-использования. К тому же, этот SDK имеет открытый исходный код. Подключить MapBox SDK можно несколькими способами, они описаны на официальном сайте, выбирайте наиболее подходящий для вас.

Итак, после подключения SDK для отображения OSM карты нам нужно в своем ViewController создать экземпляр RMMapView, инициализированный с источником класса RMOpenStreetMapSource.

RMOpenStreetMapSource *osmMapSource = [[RMOpenStreetMapSource alloc] init];
RMMapView *mapView = [[RMMapView alloc] initWithFrame:self.view.bounds andTilesource:osmMapSource];
mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:mapView];

Теперь в нашем приложении показывается отличная детализированная карта мира OpenStreetMap. Все очень просто, не так ли?

Пре-кэширование и оффлайн-режим

Теперь реализуем возможность пользователю заранее закачать участок карты в кэш и пользоваться картой при отсутствующем Интернет-соединении. Сначала добавим на экран UIProgressView для отображения прогресса загрузки карты и две кнопки: кнопку загрузки и кнопку переключения режима. Затем передадим карте наш собственный объект RMTileCache со сроком жизни кэша в 1 год для примера.

RMTileCache *tileCache = [[RMTileCache alloc] initWithExpiryPeriod:31557600.0];
_mapView.tileCache = tileCache;

Для начала асинхронной загрузки данных и отслеживания прогресса реализуем метод обработки нажатия по кнопке Download и поддержим протокол RMTileCacheBackgroundDelegate. Для примера загрузим карту города Пхеньян, который на картах Apple, кстати, отображается как простая надпись в поле и ничего вокруг.

#pragma mark - Actions
- (IBAction)downloadAction:(id)sender {
_mapView.tileCache.backgroundCacheDelegate = self;
[_mapView.tileCache beginBackgroundCacheForTileSource:_mapView.tileSource
southWest:CLLocationCoordinate2DMake(38.9796, 125.6657)
northEast:CLLocationCoordinate2DMake(39.0876, 125.8554)
minZoom:1
maxZoom:16];
}
#pragma mark - Tile Cache Delegate
- (void)tileCache:(RMTileCache *)tileCache didBeginBackgroundCacheWithCount:(int)tileCount forTileSource:(id &amp;lt;RMTileSource&amp;gt;)tileSource {
_progressView.progress = 0.0f;
_progressView.hidden = NO;
}
- (void)tileCache:(RMTileCache *)tileCache didBackgroundCacheTile:(RMTile)tile withIndex:(int)tileIndex ofTotalTileCount:(int)totalTileCount {
_progressView.progress = (float)tileIndex / (float)totalTileCount;
}
- (void)tileCacheDidFinishBackgroundCache:(RMTileCache *)tileCache {
_progressView.hidden = YES;
}
- (void)tileCacheDidCancelBackgroundCache:(RMTileCache *)tileCache {
_progressView.hidden = YES;
}

Для переключения режима воспользуемся свойством retryCount у RMOpenStreetMapSource: для оффлайн-режима будем выставлять число попыток загрузки в 0, а для онлайн – возвращать значение по умолчанию равное 3.

- (IBAction)toggleModeAction:(id)sender {
UIButton *modeButton = (UIButton *)sender;
RMOpenStreetMapSource *mapSource = (RMOpenStreetMapSource *)_mapView.tileSource;
if (mapSource.retryCount &amp;gt; 0) {
mapSource.retryCount = 0;
[modeButton setTitle:@&quot;Mode: Offline&quot; forState:UIControlStateNormal];
} else {
mapSource.retryCount = 3;
[modeButton setTitle:@&quot;Mode: Online&quot; forState:UIControlStateNormal];
}
}

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

Вывод

Как мы увидели, существует отличная альтернатива картам Apple, которую довольно легко подключать и использовать в своих приложениях. И если вы пишете приложение, предназначенное для использования в регионах с недостаточной детализацией карт Apple или для вас критичен оффлайн-режим, то при поиске альтернатив, обратите внимание на карты OpenStreetMap и MapBox SDK.

Ссылки:

http://www.openstreetmap.org

https://www.mapbox.com