В декабре Google выпустили SDK для встраивания своих карт в iOS-приложение. Последние дни я ковырялся в них, пытаясь встроить их свой проект. Небольшое описание того, как их встроить.
Создадим какое-нибудь новое приложение.
Добавим на экран новый UIView. Свяжем наш UIView с кодом через IBOutlet. Также в настройках в правой панели выставим ему класс GMSMapView. Класс выставить нужно для того, чтобы гуглокарты можно было на экране встроить в наш вид, а не просто заменить self.view на гуглокарты и получить карту на весь экран.
Импортировать SDK в проект довольно просто. Подробная инструкция, буквально пошаговая, от Google, только на русском:
- Создаём новый проект в Google APIs Console.
- Выбираем раздел Services в своём API проекте, включаем Google Maps SDK for iOS. Принимаем правила использования.
- Выбираем пункт API Access и жмём Create new iOS key.
- Вводим 1 или более bundle identifiers из файла .plist нашего приложения, вида com.example.myapp. В моём случае это makoni.Google-Maps-Demo.
- Жмём Create.
- На странице API Access находим раздел Key for iOS apps (с идентификаторами наших приложений) и видим 40-значный API-key. Он то нам и понадобится для работы.
Далее нужно добавить в проект сам SDK. Судя по описанию на сайте Google - их карта не работает со Storyboards и требует, чтобы был включён ARC (Auto Reference Counting).
- Перетаскиваем GoogleMaps.framework из скачанного и распакованного SDK в проект в группу Frameworks. Когда спросят - ставим галку Copy items into destination group's folder.
- Жмём правой кнопкой по GoogleMaps.framework внутри проекта и выбираем Показать в Finder.
- В открывшейся папке из папки Resources перетаскиваем GoogleMaps.bundle в наш проект (рекомендуют тоже в группу Frameworks тащить), когда спросят - галку напротив Copy items into destination group's folder на этот раз снимаем.
- Выбираем наш проект и выбираем пункт в разделе target.
Во вкладке Build Phases добавляем в пункте Link Binary with Libraries следующие фреймворки:- AVFoundation.framework
- CoreData.framework
- CoreLocation.framework
- CoreText.framework
- GLKit.framework
- ImageIO.framework
- libc++.dylib
- libicucore.dylib
- libz.dylib
- OpenGLES.framework
- QuartzCore.framework
- SystemConfiguration.framework
- Во вкладке Build Settings значение Architectures должно быть armv7. В секции Other Linker Flags нужно добавить -ObjC.
- В нашем AppDelegate осталось добавить строки #import <GoogleMaps/GoogleMaps.h> и добавить в метод application:didFinishLaunchingWithOptions: строку [GMSServices provideAPIKey:@"YOUR_API_KEY"]; где заменить YOUR_API_KEY своим 40-значным ключом API.
Всё, гуглокарты в проект импортированы. Можно пользоваться.
Примерное понимание того, что можно сделать с картами, даёт документация по протоколу GMSMapViewDelegate. На момент написания поста последняя версия гуглокарт для iOS 1.3.0 (май 2013).
В двух словах - можно отловить перемещение карты (изменений камеры), тап по карте, долгое нажатие по карте, тап по маркеру (по метке на карте), там по информационному окну маркера, там по Overlay, плюс можно своё информационное окно подсунуть при тапе по маркеру.
На карту можно вывести встроенные кнопки показа местонахождения пользователя и кнопку компаса.
Я сделал простой пример, в котором открывается карта с меткой на Санкт-Петербурге, а кнопка «Показать Москву» перекидывает на Москву с меткой на ней. Также если долго тыкать на какое-то место в карте - появится метка на этом месте. Описывать всё не вижу смысла, проще заглянуть в код примера.
Карта у Google гораздо подробнее, чем карты Apple, где вообще нет домов, что делает их непригодными для использования в приложениях, где нужно отобразить какой-то конкретный адрес и местоположение.
По работе я сделал с помощью карт Google почти всё необходимое - требовалось по изменению карты подгружать с сервера новые данные и отображать их в виде меток на карте. Вот только реализовать всё необходимое на данный момент не удалось.
Проблемы, с которым я столкнулся:
- при изменении карты (камеры) - событие - mapView:didChangeCameraPosition: срабатывает несколько раз. То есть пока пользователь пальцем передвигает карту - оно постоянно срабатывает. При этом моё приложение постоянно отправляет запросы на сервер, на эмуляторе оно умудряется по 5-6 запросов в секунду отправить. В условиях мобильного интернета это неразумное расходование трафика, плюс ко всему от такого количества асинхронных запросов карта начинает просто тормозить. Отловить, что карта не просто изменилась, а пользователь закончил её перемещать, нельзя. Разве что пробовать вручную как-то отслеживать - отпустил пользователь палец от экрана или нет. По-моему это просто ужасно.
UPDATE: для этой проблемы есть решение. - Нельзя отловить стандартную кнопку My Location. В приложении, что я пишу, по нажатию на неё я должен очищать метки на карте, т.к. пользователь мог переместиться в другую часть города и показывать старые метки ему не нужно, да и память они жрут. Чтобы это сделать - придётся навесить свою собственную кнопку.
-
Судя по всему, информационное окно, открывающееся по нажатию на маркер на карте - рендерится картинкой. В общем - в нём можно только задать Заголовок и текст описания. Никак более его кастомизировать, увы, нельзя. Если хочешь что-то изменить - придётся рисовать полностью своё окно со всем оформлением, реализовав метод
.- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(id<GMSMarker> *)marker
Надеюсь в следующих версиях SDK эти проблема решат.
Пример можно скачать на GitHub. Только не забудьте в файле AppDelegate.m в строке [GMSServices provideAPIKey:@""] задать ваш ключ для API, иначе карты не заработают.
Кстати, размер приложения в Google Maps SDK, вроде, приемлемый. Размер примера - 2.5 мегабайта.
Peace.