Вандад Нахавандипур - iOS. Приемы программирования
if (error!= nil){
/* Здесь обрабатываем ошибку, например отобразив окно
с предупреждением */
return;
}
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = [MKMapItem mapItemForCurrentLocation];
/* Преобразуем метку назначения CoreLocation в метку MapKit */
/* Получаем метку адреса назначения*/
CLPlacemark *placemark = placemarks[0];
CLLocationCoordinate2D destinationCoordinates =
placemark.location.coordinate;
MKPlacemark *destination = [[MKPlacemark alloc]
initWithCoordinate: destinationCoordinates
addressDictionary: nil];
request.destination = [[MKMapItem alloc]
initWithPlacemark: destination];
/* Мы собираемся попасть в точку назначения на автомобиле */
request.transportType = MKDirectionsTransportTypeAutomobile;
/* Получаем направления */
MKDirections *directions = [[MKDirections alloc]
initWithRequest: request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
/* Можно вручную выполнить синтаксический разбор отклика, но здесь мы
поступим иначе и воспользуемся приложением Maps (Карты) для отображения
начальной и конечной точек. Делать такой вызов API необязательно,
так как ранее мы уже подготовили элементы карты. Но здесь вызов
делается в демонстрационных целях. Мы показываем, что в отклике
с направлениями содержится не только информация о начальной и конечной
точках */
/* Отображаем направления в приложении Maps */
[MKMapItem
openMapsWithItems:@[response.source, response.destination]
launchOptions:@{
MKLaunchOptionsDirectionsModeKey:
MKLaunchOptionsDirectionsModeDriving}];
}];
}];
self.window = [[UIWindow alloc]
initWithFrame: [[UIScreen mainScreen] bounds]];
// Точка переопределения для дополнительной настройки после запуска приложения
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Я запущу это приложение в симуляторе iOS, так как выбранная мной конечная точка находится слишком близко от того места, где я нахожусь (начальной точки). Результат получится примерно таким, как на рис. 9.5.
Рис. 9.5. Отображение направлений на карте
См. также
Раздел 9.3.
Глава 10. Реализация распознавания жестов
10.0. Введение
Жест (Gesture) — это комбинация событий касания. Жесты применяются, например, в стандартном приложении Photo (Фото) для iOS. В этой программе пользователь может увеличивать или уменьшать фотографию, двигая двумя пальцами в разные стороны или навстречу друг другу. Некоторые образцы кода, чаще всего применяемого для обнаружения событий, связанных с жестикуляцией, инкапсулированы во встроенные классы iOS SDK, которые пригодны для многократного использования. Эти классы можно применять для обнаружения смахивания (Swipe), щипка (Pinch), панорамирования (Pan), нажатия (Tap), перетаскивания (Drag), долгого нажатия (Long Press) и вращения (Rotation).
Распознаватели жестов необходимо добавлять к экземплярам класса UIView. Один вид может быть связан с несколькими распознавателями жестов. Как только вид регистрирует жест, при необходимости он должен будет передать данный жест другим видам, расположенным ниже в иерархической цепочке.
Некоторые события, возникающие при работе приложения, могут быть сложны для обработки и требовать, чтобы одно и то же событие обнаруживалось в разных видах отдельно взятого приложения. Таким образом, возникает необходимость в распознавателях жестов, пригодных для многократного использования. В iOS SDK 5 интегрированы распознаватели шести жестов, таких как:
• смахивание;
• вращение;
• щипок;
• панорамирование;
• длинное нажатие;
• нажатие.
Общий принцип обработки жестов с помощью этих встроенных распознавателей таков.
1. Для требуемого распознавателя жестов создается объект данных нужного типа.
2. Этот объект добавляется в качестве распознавателя жестов к тому виду, который будет принимать жесты.
3. Пишется метод, вызываемый при возникновении жеста и осуществляющий указанное вами действие.
Метод, который ассоциируется в качестве целевого метода с любым распознавателем жестов, должен следовать перечисленным далее правилам:
• возвращать void;
• либо не принимать параметров, либо принимать единственный параметр типа UIGestureRecognizer, в котором система будет передавать распознаватель жестов, вызывающий данный метод.
Рассмотрим два примера:
— (void) tapRecognizer:(UITapGestureRecognizer *)paramSender{
/* */
}
— (void) tapRecognizer{
/* */
}
Распознаватели жестов делятся на две категории: дискретные (Discrete) и непрерывные (Continuous). Дискретные распознаватели жестов регистрируют связанные с ними события жестов, а после этого вызывают метод в своем обладателе. Непрерывные распознаватели жестов сообщают своему объекту-обладателю о жесте на протяжении всего того времени, пока этот жест осуществляется, и многократно вызывают метод в своем целевом объекте, пока это событие не закончится.
Например, событие двойного нажатия является дискретным. Хотя оно и состоит из двух нажатий, система улавливает, что промежуток между ними был очень кратким и оба нажатия можно воспринимать как единое событие. Распознаватель двойного нажатия вызывает в своем целевом объекте соответствующий метод, как только будет зарегистрировано двойное нажатие.
Вращение, напротив, обрабатывается непрерывным распознавателем жестов. Как только пользователь начинает вращательный жест, начинается и работа распознавателя, а оканчивается этот жест, только когда пользователь отрывает пальцы от экрана. Метод, предоставляемый классу распознавателя вращательных жестов, вызывается с краткими интервалами до тех пор, пока событие не завершится.
Распознаватели жестов можно добавлять к любому экземпляру класса UIView с помощью метода addGestureRecognizer:, относящегося к виду. При необходимости распознаватели можно удалять, пользуясь методом removeGestureRecognizer:.
У класса UIGestureRecognizer есть свойство под названием state. Свойство state представляет различные состояния распознавателя жестов, которые он принимает в ходе распознавания. Последовательности претерпеваемых состояний различаются у дискретных и непрерывных распознавателей жестов.
Дискретный распознаватель жестов может проходить через три следующих состояния:
• UIGestureRecognizerStatePossible;
• UIGestureRecognizerStateRecognized;
• UIGestureRecognizerStateFailed.
В зависимости от ситуации дискретный распознаватель жестов может сообщать своей цели о состоянии UIGestureRecognizerStateRecognized либо о состоянии UIGestureRecognizerStateFailed, если в процессе распознавания возникнет ошибка.
Непрерывные распознаватели жестов претерпевают иную серию состояний, которые посылают своим целям:
• UIGestureRecognizerStatePossible;
• UIGestureRecognizerStateBegan;
• UIGestureRecognizerStateChanged;
• UIGestureRecognizerStateEnded;
• UIGestureRecognizerStateFailed.
Состояние распознавателя жестов меняется на UIGestureRecognizerStatePossible в том случае, когда распознаватель собирает в виде информацию о событиях касаний и в любой момент может обнаружить интересующий его жест. Кроме вышеупомянутых состояний непрерывного распознавателя жестов может возникать и состояние UIGestureRecognizerStateCancelled, если жест по какой-то причине прерывается. Например, жест панорамирования может быть прерван входящим телефонным вызовом. В данном случае распознаватель жестов перейдет в состояние UIGestureRecognizerStateCancelled и перестанет отправлять объекту-получателю какие-либо сообщения, если пользователь не повторит всю жестовую последовательность.
Опять же, если непрерывный распознаватель жестов столкнется с ситуацией, которую не удается разрешить с помощью имеющихся у системы возможностей, возникнет состояние UIGestureRecognizerStateFailed, а не UIGestureRecognizerStateEnded.
10.1. Обнаружение жестов смахивания
Постановка задачи
Необходимо идентифицировать скользящие жесты смахивания, которые пользователь осуществляет на виде, например, когда убирает картинку с окна.
Решение
Инстанцируйте объект типа UISwipeGestureRecognizer и добавьте его к экземпляру UIView:
#import «ViewController.h»
@interface ViewController ()
@property (nonatomic, strong)
UISwipeGestureRecognizer *swipeGestureRecognizer;
@end
@implementation ViewController