iOS. Приемы программирования — страница 75 из 124

Постановка задачи

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

Решение

Создайте экземпляр класса UITapGestureRecognizer и добавьте его к целевому виду с помощью метода экземпляра addGestureRecognizer:, относящегося к классу UIView. Рассмотрим определение контроллера вида (.h-файл):


#import «ViewController.h»


@interface ViewController ()


@property (nonatomic, strong)

UITapGestureRecognizer *tapGestureRecognizer;


@end

@implementation ViewController

Реализация метода экземпляра viewDidLoad контроллера вида такова:

— (void)viewDidLoad {

[super viewDidLoad];


/* Создаем распознаватель жестов-нажатий. */

self.tapGestureRecognizer = [[UITapGestureRecognizer alloc]

initWithTarget: self

action:@selector(handleTaps:)];


/* Количество пальцев, которые должны находиться на экране. */

self.tapGestureRecognizer.numberOfTouchesRequired = 2;


/* Общее количество касаний, которое должно быть выполнено, прежде

чем жест будет распознан. */

self.tapGestureRecognizer.numberOfTapsRequired = 3;


/* Добавляем к виду этот распознаватель жестов. */

[self.view addGestureRecognizer: self.tapGestureRecognizer];


}

Обсуждение

Распознаватель жестов-нажатий лучше всех остальных распознавателей подходит для обнаружения обычных нажатий (толчков) на экран. Нажатие — это событие, происходящее, когда пользователь касается пальцем какой-то точки экрана, а потом отрывает палец от него. Жест нажатия является дискретным.

Метод locationInView: класса UITapGestureRecognizer можно применять для обнаружения точки, в которой произошло событие нажатия. Если для регистрации нажатия требуется более одного касания, то можно вызвать метод locationOfTouch: inView: класса UITapGestureRecognizer, определяющий точки отдельных касаний. В коде мы задали для свойства numberOfTouchesRequired распознавателя жестов-нажатий значение 2. При таком значении распознавателю жестов необходимо, чтобы в момент каждого нажатия на экране находились два пальца. Количество нажатий, требуемое, чтобы жесты-нажатия стали распознаваться, определено как 3. Я сделал это с помощью свойства numberOfTapsRequired. Я указал метод handleTaps: в качестве целевого метода распознавателя жестов-нажатий:


— (void) handleTaps:(UITapGestureRecognizer*)paramSender{


NSUInteger touchCounter = 0;

for (touchCounter = 0;

touchCounter < paramSender.numberOfTouchesRequired;

touchCounter++){

CGPoint touchPoint =

[paramSender locationOfTouch: touchCounter

inView: paramSender.view];

NSLog(@"Touch #%lu: %@",

(unsigned long)touchCounter+1,

NSStringFromCGPoint(touchPoint));

}


}


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


Touch #1: {107, 186}

Touch #2: {213, 254}

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

Кроме того, необходимо упомянуть о методе NSStringFromCGPoint, который, как понятно из его названия[10], может преобразовать структуру CGPoint в строку NSString. Эта функция применяется для превращения CGPoint каждого прикосновения к экрану в NSString, а данную строку мы уже можем записать в окне консоли, воспользовавшись NSLog. Чтобы открыть окно консоли, выполните Run — Console (Запустить— Консоль).

10.6. Обнаружение щипка

Постановка задачи

Необходимо предоставить пользователю возможность выполнять движения щипка.

Решение

Создайте экземпляр класса UIPinchGestureRecognizer и добавьте его к вашему целевому виду, воспользовавшись методом экземпляра addGestureRecognizer:, относящимся к классу UIView:


— (void)viewDidLoad {

[super viewDidLoad];


CGRect labelRect = CGRectMake(0.0f, /* X */

0.0f, /* Y */

200.0f, /* Ширина */

200.0f); /* Высота */


self.myBlackLabel = [[UILabel alloc] initWithFrame: labelRect];

self.myBlackLabel.center = self.view.center;

self.myBlackLabel.backgroundColor = [UIColor blackColor];


/* Без этой строки распознаватель щипков работать не будет. */

self.myBlackLabel.userInteractionEnabled = YES;

[self.view addSubview: self.myBlackLabel];


/* Создаем распознаватель щипков. */

self.pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc]

initWithTarget: self

action:@selector(handlePinches:)];


/* Добавляем этот распознаватель жестов к виду. */

[self.myBlackLabel

addGestureRecognizer: self.pinchGestureRecognizer];


}

Контроллер вида определяется так:

#import «ViewController.h»


@interface ViewController ()

@property (nonatomic, strong)

UIPinchGestureRecognizer *pinchGestureRecognizer;


@property (nonatomic, strong) UILabel *myBlackLabel;


@property (nonatomic, unsafe_unretained) CGFloat currentScale;


@end

Обсуждение

Щипки позволяют пользователю легко масштабировать (увеличивать и уменьшать) элементы графического интерфейса. Например, браузер Safari в iOS дает возможность щипком на веб-странице увеличивать ее содержимое. Щипок работает в двух направлениях: увеличение и уменьшение масштаба. Это непрерывный жест, который на сенсорном экране всегда выполняется двумя пальцами.

Данный распознаватель жестов может пребывать в следующих состояниях:

• UIGestureRecognizerStateBegan;

• UIGestureRecognizerStateChanged;

• UIGestureRecognizerStateEnded.


Как только щипок распознан, вызывается действующий метод целевого объекта (и будет последовательно вызываться до тех пор, пока щипок не окончится). В действующем методе вы получаете доступ к двум очень важным методам распознавателя щипков: scale и velocity. scale — это коэффициент, на который нужно изменить размер элемента графического интерфейса по осям X и Y, чтобы отразить таким образом размер пользовательского жеста. velocity — это скорость щипка, измеряемая в пикселах в секунду. Скорость имеет отрицательное значение, если пальцы движутся навстречу друг другу, и положительное — если они перемещаются в разные стороны.

Значение свойства scale можно передать функции CGAffineTransformMakeScale из фреймворка Core Graphics, чтобы получить аффинное преобразование. Такое преобразование применимо к свойству transform любого экземпляра класса UIView, оно позволяет изменять преобразование этого элемента. Мы воспользуемся этой функцией следующим образом:


— (void) handlePinches:(UIPinchGestureRecognizer*)paramSender{


if (paramSender.state == UIGestureRecognizerStateEnded){

self.currentScale = paramSender.scale;

} else if (paramSender.state == UIGestureRecognizerStateBegan &&

self.currentScale!= 0.0f){

paramSender.scale = self.currentScale;

}


if (paramSender.scale!= NAN &&

paramSender.scale!= 0.0){

paramSender.view.transform =

CGAffineTransformMakeScale(paramSender.scale,

paramSender.scale);

}


}

Поскольку свойство scale распознавателя жестов сбрасывается всякий раз, когда регистрируется новый щипок, мы сохраняем последнее значение этого свойства в общем свойстве экземпляра (Instance Property) контроллера вида, называемом currentScale. В следующий раз, когда будет распознан новый жест, мы отсчитываем коэффициент масштабирования от последнего зафиксированного значения, что и продемонстрировано в коде.

Глава 11. Сетевые функции, JSON, XML и Twitter