Отображение карт

Платформа Набора Карты позволяет Вам встроить полностью функциональный интерфейс карты в свое приложение. Поддержка карты, предоставленная этой платформой, включает много функций приложения Карт и в iOS и в OS X. Можно вывести на экран стандартную информацию о карте уличного уровня, спутниковое формирование изображений или комбинацию двух. Можно масштабировать, панорамировать, и передать карту программно, вывести на экран 3D здания и аннотировать карту пользовательской информацией. Платформа Набора Карты также предоставляет автоматическую поддержку для сенсорных событий, позволяющих пользователям масштабировать и панорамировать карту.

Для использования функций платформы Набора Карты включите возможность Карт в проекте XCode (выполнение так также добавляет надлежащее право на Приложение ID). Обратите внимание на то, что единственный способ распределить основанное на картах приложение через App Store Хранилища или Mac приложения для iOS. Если Вы незнакомы с правами, подписыванием кода и настройкой, начните узнавать о них в Быстром запуске Распределения приложений. Для получения общей информации о классах платформы Набора Карты, посмотрите Ссылку Платформы MapKit.

Понимание геометрии карты

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

Отобразите системы координат

Для понимания систем координат, используемых Набором Карты, это помогает понять, как трехмерная поверхность Земли отображается на двумерной карте. Рисунок 5-1 показывает, как поверхность Земли может быть отображена на двумерной поверхности.

Рисунок 5-1  , Отображающий сферические данные на плоскую поверхность

Набор карты использует Меркаторскую проекцию карты, которая является определенным типом цилиндрической проекции карты как один показанный на рисунке 5-1. В цилиндрической проекции карты координаты сферы отображаются на поверхность цилиндра, тогда развернутого для генерации плоской карты. В такой проекции строки долготы, обычно сходящиеся в полюсах, становятся параллельными вместо этого, заставляя континентальные массивы быть искаженными, поскольку Вы переезжаете от экватора. Преимущество Меркаторской проекции состоит в том, что содержание карты масштабируется в пути, приносящем преимущества общей навигации. В частности, на Меркаторской проекции карты, прямая линия, проведенная между любыми двумя точками на карте, приводит к курсу, возглавляющему, который может использоваться в фактической навигации на поверхности Земли. Проекция, используемая Набором Карты, использует Главный меридиан в качестве своего центрального меридиана.

Как Вы указываете, что точки данных на карте зависят от того, как Вы намереваетесь использовать их. Набор карты поддерживает три основных системы координат для указания точек данных карты:

  • Координата карты является широтой и долготой на сферическом представлении Земли. Координаты карты являются основным способом указать расположения на земном шаре. Вы указываете отдельные значения координаты карты с помощью CLLocationCoordinate2D структура. Можно указать области с помощью MKCoordinateSpan и MKCoordinateRegion структуры.

  • Точка карты является значением x и y на Меркаторской проекции карты. Точки карты используются для многих связанных с картой вычислений вместо координат карты, потому что они упрощают математику, вовлеченную в вычисления. В Вашем приложении Вы используете точки карты прежде всего при указании формы и позиции пользовательских оверлейных программ карты. Вы указываете отдельные точки карты с помощью MKMapPoint структура. Можно указать области с помощью MKMapSize и MKMapRect структуры.

  • Точка является графическим модулем, связанным с системой координат объекта представления. Точки карты и координаты карты должны быть отображены на точках прежде, чем нарисовать пользовательское содержание в представлении. Вы указываете отдельные точки с помощью CGPoint структура. Можно указать области с помощью CGSize и CGRect структуры.

В большинстве ситуаций система координат, которую необходимо использовать, предопределяется интерфейсами Набора Карты, которые Вы используете. Когда дело доходит до того, чтобы хранить фактические данные в файлах или в Вашем приложении, координаты карты являются точными, переносимыми, и наилучший вариант для того, чтобы хранить данные расположения. Базовое Расположение также использует координаты карты при указании значений расположения.

Преобразование между системами координат

Несмотря на то, что Вы обычно указываете точки на карте с помощью широты и значений долготы, могут быть времена, когда необходимо преобразовать в и от других систем координат. Например, Вы обычно используете точки карты при указании формы оверлейных программ. Таблица 5-1 перечисляет подпрограммы преобразования, которые Вы используете для преобразования от одной системы координат до другого. Большинство этих преобразований требует объекта представления, потому что они включают преобразование в или от точек.

Табличные 5-1  подпрограммы преобразования системы координат Карты

Преобразуйте из

Преобразуйте в

Подпрограммы преобразования

Координаты карты

Точки

convertCoordinate:toPointToView: (MKMapView)

convertRegion:toRectToView: (MKMapView)

Координаты карты

Точки карты

MKMapPointForCoordinate

Точки карты

Координаты карты

MKCoordinateForMapPoint

MKCoordinateRegionForMapRect

Точки карты

Точки

pointForMapPoint: (MKOverlayRenderer)

rectForMapRect: (MKOverlayRenderer)

Точки

Координаты карты

convertPoint:toCoordinateFromView: (MKMapView)

convertRect:toRegionFromView: (MKMapView)

Точки

Точки карты

mapPointForPoint: (MKOverlayRenderer)

mapRectForRect: (MKOverlayRenderer)

Добавление представления карты к пользовательскому интерфейсу

MKMapView класс является автономным интерфейсом для представления данных карты в Вашем приложении: Это предоставляет поддержку для отображения данных карты, управления взаимодействием с пользователем и хостинга пользовательское содержание, предоставленное Вашим приложением. Никогда не разделяйте на подклассы MKMapView. Вместо этого встройте его как есть в иерархию представления Вашего приложения.

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

Можно добавить представление карты к приложению программно или использующий Интерфейсного Разработчика:

Поскольку представление карты является представлением, можно управлять им тот же способ, которым Вы управляете другими представлениями. Можно изменить его размер и позицию в иерархии представления, сконфигурировать его способы поведения автоизменения размеров и добавить подпредставления к нему. Само представление карты является непрозрачным контейнером для сложной иерархии представления, обрабатывающей дисплей связанных с картой данных и всех взаимодействий с теми данными. Любые подпредставления, которые Вы добавляете к представлению карты, сохраняют позицию, указанную их frame свойство и не прокручивает с содержанием карты. Если Вы хотите, чтобы содержание осталось фиксированным относительно определенной координаты карты (и таким образом прокручивать с самой картой), необходимо использовать аннотации или оверлейные программы, как описано в Аннотировании Карт. Лучше избегать любой модификации иерархии представления карты.

Новые карты сконфигурированы для принятия взаимодействия с пользователем и данных карты дисплея только. По умолчанию стандартная карта использует 3D перспективу путем включения подачи, наклоняющей карту и вращение, позволяющее карте вывести на экран заголовок. Можно указать подачу и вращение путем создания MKMapCamera объект. Можно сконфигурировать карту для отображения спутникового формирования изображений или смеси спутника и данных карты путем изменения Атрибута типа карты в Интерфейсном Разработчике или путем изменения значения в mapType свойство. Если Вы хотите ограничить взаимодействие с пользователем, можно изменить значения в rotateEnabled, pitchEnabled, zoomEnabled, и scrollEnabled свойства также. Если Вы хотите реагировать на взаимодействие с пользователем, используйте делегата, как описано в Использовании Делегата для Ответа на Взаимодействие с пользователем.

Конфигурирование свойств карты

MKMapView класс имеет несколько свойств, которые можно сконфигурировать программно. Эти свойства управляют важной информацией такой как, какая часть карты в настоящее время видима, выведено ли содержание на экран в 3D, и какое взаимодействие с пользователем позволяется.

Установка видимой части карты

region свойство MKMapView класс управляет в настоящее время видимой частью карты. Когда карта сначала создается, ее видимая область обычно устанавливается в весь мир. Другими словами, область охватывает область, показывающую как можно больше карты. Можно изменить эту область путем присвоения нового значения region свойство. Это свойство содержит MKCoordinateRegion структура, которой показали определение ниже.

typedef struct {
   CLLocationCoordinate2D center;
   MKCoordinateSpan span;
} MKCoordinateRegion;

Интересная часть MKCoordinateRegion структура является промежутком. Промежуток определяет, сколько из карты в данной точке должно быть видимо. Несмотря на то, что промежуток походит на значения ширины и высоты прямоугольника, он указал координаты карты использования и таким образом измеряется в градусах, минуты и секунды. Один градус широты эквивалентен приблизительно 111 километрам, но продольные расстояния меняются в зависимости от широты. На экватор один градус долготы эквивалентен приблизительно 111 километрам, но в полюсах это значение является нулем. Если Вы предпочитаете указывать промежуток в метрах, используйте MKCoordinateRegionMakeWithDistance создать структуру данных области с метром оценивает вместо градусов.

Значение Вы присваиваетесь к region свойство (или набор с помощью setRegion:animated: метод), обычно не то же значение, которое в конечном счете сохранено тем свойством. Установка промежутка области номинально определяет прямоугольник, который Вы хотите просмотреть, но также и неявно устанавливает уровень изменения масштаба для самого представления карты. Представление карты не может вывести на экран произвольные уровни изменения масштаба и должно скорректировать любые области, которые Вы указываете для соответствия уровней изменения масштаба, которые оно поддерживает. Это выбирает уровень изменения масштаба, позволяющий Вашему всему региону быть видимым при тихом заполнении как можно большего количества экрана. Это тогда корректируется region свойство соответственно. Узнать получающуюся область, фактически не изменяя значение в region свойство, используйте regionThatFits: метод представления карты.

Отображение 3D карты

3D карта является стандартной 2D картой, просматриваемой под углом от точки наблюдения выше плоскости карты. Высота точки, объединенная с углом, от которого просматривается карта, определяет промежуток и наклон (также известный как подача) 2D поверхности карты. Пользователи могут скорректировать подачу и вращение карты и в iOS 7 и OS X v10.9 и позже, можно использовать MKMapCamera класс, чтобы программно скорректировать 3D карту.

Объект камеры использует следующие свойства для определения появления 3D карты:

  • Высота. Высота камеры (в метрах) выше поверхности карты.

  • Подача. Угол тот, в который наклоны фотоаппарата, относительно земли. (Обратите внимание на то, что подача 0 производит стандартную 2D карту, потому что камера выглядит прямой вниз.)

  • Заголовок. Кардинальное направление, в котором обращается камера.

  • Центр. Точка на поверхности карты, появляющейся в центре экрана или окна.

В iOS 7 и OS X v10.9 и позже, карты 3D по умолчанию, который может влиять на Ваше приложение следующими способами:

  • Поскольку имеющая определенную высоту карта может представить небо, пользователи видят области, которые являются вне границ карты. Обязательно проверьте законность значений, возвращенных методами преобразования представления карты (такой как convertPoint:toCoordinateFromView:) таким образом, Ваше приложение не пытается поместить аннотации в небо.

  • Если Набор Карты обнаруживает бессмысленное значение подачи, такое как 180 градусов (т.е. смотря прямо на небо), это фиксирует подачу к рыночной стоимости.

  • Часто, видимая область 3D карты не является прямоугольной, когда она просматривается в двух размерностях. В этом сценарии, region и visibleMapRect свойства указывают прямоугольную область, содержащую 2D приближение видимой области имеющей определенную высоту карты.

  • Аннотации автоматически поддерживают свой размер и ориентацию, как раз когда карта вращается или делает подачу, таким образом, Ваши иллюстрации не будут искажены или изменили размеры. (Узнайте больше о работе с аннотациями в Аннотировании Карт.)

По большей части 3D карты работают то же в приложениях OS X и iOS. Несколько различий между платформами находятся прежде всего в пользовательском интерфейсе и в некоторых типах основного объекта: 3D карта в компасе отображений приложения OS X и средствах управления изменением масштаба и метке приписывания данных карты; 3D карта в приложении для iOS не выводит на экран эти элементы. В OS X Набор Карты определяет объекты, наследовавшиеся от NSView и NSImage; в iOS аналогичные объекты наследовались от UIView и UIImage.

В iOS 7 и OS X v10.9 и позже, MKMapView класс включает a camera свойство можно использовать, чтобы создать и получить доступ к 3D карте, сохранить и восстановить состояние карты, и программно масштабировать и панорамирование. Например, можно легко создать 3D карту расположения путем указания позиции и высоты, из которой можно просмотреть расположение, прося, чтобы Набор Карты создал надлежащий объект камеры, и присвоив объект представлению карты camera свойство. Перечисление 5-1 показывает, как сделать это.

Перечисление 5-1  , Создающее 3D карту

// Create a coordinate structure for the location.
CLLocationCoordinate2D ground = CLLocationCoordinate2DMake(myLatitude, myLongitude);
 
// Create a coordinate structure for the point on the ground from which to view the location.
CLLocationCoordinate2D eye = CLLocationCoordinate2DMake(eyeLatitude, eyeLongitude);
 
// Ask Map Kit for a camera that looks at the location from an altitude of 100 meters above the eye coordinates.
MKMapCamera *myCamera = [MKMapCamera cameraLookingAtCenterCoordinate:ground fromEyeCoordinate:eye eyeAltitude:100];
 
// Assign the camera to your map view.
mapView.camera = myCamera;

Поскольку объект камеры полностью определяет появление карты, это - хорошая идея использовать его, чтобы сохранить и восстановить состояние Вашей карты. MKMapCamera класс соответствует NSSecureCoding протокол, таким образом, можно использовать объект камеры с archiver или, в приложении для iOS, восстановление состояния UIKit APIs. Перечисление 5-2 показывает пример сохранения и восстановления состояния карты.

  Архивация перечисления 5-2 и разархивирование карты

MKMapCamera *camera = [map camera]; // Get the map's current camera.
[NSKeyedArchiver archiveRootObject:camera toFile:stateFile]; // Archive the camera.
MKMapCamera *camera = [NSKeyedUnarchiver unarchiveObjectWithFile:stateFile]; // Unarchive the camera.
[map setCamera:camera]; // Restore the map.

Изменение масштаба и панорамирование содержания карты

Изменение масштаба и панорамирование позволяют Вам изменять видимую часть карты в любое время:

  • Панорамировать карту (но сохранить тот же уровень изменения масштаба, подачу, и вращение), изменяют значение в centerCoordinate свойство представления карты или камеры или вызова представление карты setCenterCoordinate:animated: или setCamera:animated: методы.

  • Чтобы изменить уровень изменения масштаба (и дополнительно панорамировать карту), измените значение в region свойство карты просматривает или вызывает setRegion:animated: метод. Можно также варьироваться высота камеры в 3D карте (удвоение, или сокращение вдвое высоты является приблизительно тем же как увеличиванием масштаб или одним уровнем).

Если Вы только хотите панорамировать карту, необходимо сделать так путем изменения только centerCoordinate свойство. Попытка панорамировать карту путем изменения region свойство обычно вызывает изменение на уровне изменения масштаба также, потому что, изменяя любую часть причин области представление карты для оценки уровня изменения масштаба должно было вывести на экран ту область соответственно. Изменения в текущей широте почти всегда заставляют уровень изменения масштаба изменяться, и другие изменения могли бы заставить различный уровень изменения масштаба быть выбранным также. Используя centerCoordinate свойство (или setCenterCoordinate:animated: метод), позволяет карте просмотреть, знают, что это должно оставить уровень изменения масштаба без изменений и обновить промежуток по мере необходимости. Например, этот код панорамирует карту налево наполовину текущая ширина карты путем нахождения координаты в левом краю карты и использования его в качестве новой центральной точки.

CLLocationCoordinate2D mapCenter = myMapView.centerCoordinate;
mapCenter = [myMapView convertPoint:
               CGPointMake(1, (myMapView.frame.size.height/2.0))
               toCoordinateFromView:myMapView];
[myMapView setCenterCoordinate:mapCenter animated:YES];

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

MKCoordinateRegion theRegion = myMapView.region;
 
// Zoom out
theRegion.span.longitudeDelta *= 2.0;
theRegion.span.latitudeDelta *= 2.0;
[myMapView setRegion:theRegion animated:YES];

Отображение текущего расположения пользователя на карте

Набор карты включает встроенную поддержку отображения текущего расположения пользователя на карте. Для показа этого расположения установите showsUserLocation свойство Вашей карты просматривает объект к YES. Выполнение так заставляет представление карты использовать Базовое Расположение, чтобы найти расположение пользователя и добавить аннотацию типа MKUserLocation к карте.

Добавление MKUserLocation об объекте пометок к карте сообщает делегат таким же образом, который пользовательские аннотации. Если Вы хотите связать пользовательское представление аннотации с расположением пользователя, необходимо возвратить то представление из объекта делегата mapView:viewForAnnotation: метод. Если Вы хотите использовать представление аннотации по умолчанию, возвратиться nil от того метода. Для узнавания больше о добавляющих аннотациях к карте см. Карты Аннотирования.

Создание снимка карты

В некоторых случаях это не целесообразно добавлять полностью интерактивное представление карты к Вашему приложению. Например, если Ваше приложение позволяет пользователям выбрать расположение из списка прокрутки изображений карты, разрешение взаимодействия с каждой картой является ненужным и может повредить прокрутку производительности. Другая причина создать статическое изображение карты состоит в том, чтобы реализовать опцию печати. В обеих ситуациях можно использовать a MKMapSnapshotter объект создать статическое изображение карты асинхронно. Получающийся снимок содержит представление изображения, к которому можно применить все эффекты, что Вы применяетесь к другим изображениям в своем приложении.

В целом выполните эти шаги для создания снимка карты:

  1. Удостоверьтесь, что у Вас есть сетевое соединение и что Ваше приложение находится на переднем плане.

  2. Создайте и сконфигурируйте MKMapSnapshotOptions объект, указывающий появление карты и размер вывода. (Приложение для iOS может также указать масштаб для вывода.)

  3. Создайте MKMapSnapshotter возразите и инициализируйте его с опциями, которые Вы указали на шаге 1.

  4. Вызвать startWithCompletionHandler: запустить асинхронную задачу создания снимка.

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

В приложении для iOS Вы часто используете drawContentForPageAtIndex:inRect: реализовать печать. Поскольку этот метод ожидает получать печатаемое содержание синхронно, необходимо изменить шаги создания снимка для включения использования семафора отгрузки и очереди, помогающих Вам блокировать на завершении снимка. (Для узнавания больше о семафорах отгрузки и очередях посмотрите Используя Семафоры Отгрузки для Регулирования Использования Конечных Ресурсов.)

Создать снимок карты для печати в приложении для iOS:

  1. Создайте и сконфигурируйте MKMapSnapshotOptions объект. (Обратите внимание на то, что приложения для iOS обычно указывают масштаб 2, потому что большинство принтеров с высокой разрешающей способностью.)

  2. Создайте MKMapSnapshotter возразите и инициализируйте его с опциями, которые Вы указали на шаге 1.

  3. Создайте семафор отгрузки, позволяющий Вам ожидать ресурса — в этом случае, снимок — для становления доступным.

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

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

  6. Вызвать startWithQueue:completionHandler: начинать генерировать снимок асинхронно.

  7. Когда задача завершится, передайте изображение снимка drawContentForPageAtIndex:inRect: для печати.

Код в Перечислении 5-3 реализует большинство шагов для печати снимка карты. Код не показывает создание MKMapSnapshotOptions объект.

Перечисление 5-3  , Создающее карту, создает снимки для печати

// Initialize the semaphore to 0 because there are no resources yet.
dispatch_semaphore_t snapshotSem = dispatch_semaphore_create(0);
 
// Get a global queue (it doesn't matter which one).
dispatch_queue_t queue = dispatch_get_global_queue(myQueuePriorityLevel, 0);
 
// Create variables to hold return values. Use the __block modifier because these variables will be modified inside a block.
__block MKMapSnapshot *mapSnapshot = nil;
__block NSError *error = nil;
 
// Start the asynchronous snapshot-creation task.
[snapshotter startWithQueue:queue
          completionHandler:^(MKMapSnapshot *snapshot, NSError *e) {
    mapSnapshot = snapshot;
error = e;
    // The dispatch_semaphore_signal function tells the semaphore that the async task is finished, which unblocks the main thread.
    dispatch_semaphore_signal(snapshotSem);
}];
 
// On the main thread, use dispatch_semaphore_wait to wait for the snapshot task to complete.
dispatch_semaphore_wait(snapshotSem, DISPATCH_TIME_FOREVER);
if (error) { // Handle error. }
 
// Get the image from the newly created snapshot.
UIImage *image = mapSnapshot.image;
// Optionally, draw annotations on the image before displaying it.

Используя делегата для ответа на взаимодействие с пользователем

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

Для получения информации об обработке изменений, связанных с аннотациями и оверлейными программами, см. Карты Аннотирования.

Запуск приложения карт

Если Вы предпочли бы отображать информацию о карте в приложении Карт в противоположность Вашему собственному приложению, можно запустить Карты программно с помощью одного из двух методов:

Предпочтительный способ открыть приложение Карт состоит в том, чтобы использовать MKMapItem класс. Этот класс предлагает обоим openMapsWithItems:launchOptions: метод класса и openInMapsWithLaunchOptions: метод экземпляра для открытия приложения и отображения расположений или направлений.

Для примера, показывающего, как открыть приложение Карт, посмотрите То, чтобы просить, чтобы Приложение Карт Вывело на экран Направления.