Gangstar: West Coast Hustle - подробности Dexter: The Game - новое видео…
Июл 24

Поздравляем всех с выходом iPhone 3.0!

В связи с радостным событием и с открывшейся возможностью обсудить больше не конфиденциальную новинку, предлагаем вашему вниманию серию уроков “Новое в iPhone 3.0″. 

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

NSUndoManager

За функции отмены/повтора отвечает класс “NSUndoManager“, информацию о котором можно найти здесь (на англ. языке). Принцип его работы заключается в хранении стека сообщений, который при пересылке последовательно отменяет последнее действие, потом предпоследнее и так далее до возвращения в исходное состояние.

Проиллюстрируем все сказанное выше на конкретном примере. Предположим, власти города, озабоченные постоянно растущим количеством грузовиков на улицах, решили собрать по ним статистические данные. Подсчитываться грузовики будут специальным персоналом на улицах с помощью приложений iPhone. Увидел грузовик — нажал кнопку. Ой-ой. Приняли за грузовик и? Трясем устройство, отменяя последнее действие. 

Взяв за основу код без функций отмены/повтора, попробуем добавить к нему эти возможности. 

Исходный код/GitHub

Код к уроку http://github.com/dcgrigsby/TallyTrucks/tree/master можно найти на GitHub. Чтобы загрузить себе копию, создайте клон репозитория.

Откройте терминал и переключитесь на директорию, куда планируете поместить код.

Выполните клонирование, набрав git clone git://github.com/dcgrigsby/TallyTrucks.git

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

В исходной папке

Введите git checkout 2d3a8136f43a1bba5183b1160c165aea24b705f2

Ориентация

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

В файле “TallyTrucksViewController.m:” по аналогии со всеми приложениями на базе Objective-C мы пересылаем сообщения. Для прокрутки счетчика вперед отсылается сообщение “addATruck“, назад — “removeATruck“.

Проанализируем происходящее в свете терминов “NSUndoManager“. По законам физики для каждого действия необходимо равное ему по силу и прикладываемое в противоположном направлении противодействие. Если пользователь щелкнул на кнопке, запускающей “addATruck“, для отмены действия нам понадобится выполнить “removeATruck“.

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

Добавляем NSUndoManager

Менеджер отмены действий мы добавим к классу контроллера представления как переменную экземпляра: 

Отредактируйте файл “TallyTrucksViewController.h” (измененные фрагменты выделены черным): 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import

@interface TallyTrucksViewController : UIViewController {
IBOutlet UIButton *button;
int i;
NSUndoManager *undoManager;
}

@property (nonatomic,retain) NSUndoManager *undoManager;

-(IBAction)buttonPressed;
-(void)addATruck;
-(void)removeATruck;
-(void)updateTitle;

@end

Всего изменений в файле “TallyTrucksViewController.m” два. 

Во-первых, синтезируем свойство, задекларированное в файле .h. Добавьте…

1
@synthesize undoManager;

… после предложения “the @implementation TallyTrucksViewController“.

Во-вторых, обновите методы “viewDidLoad” и “dealloc” (изменения выделены черным).

1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad {
[super viewDidLoad];
i = 0;
undoManager = [[NSUndoManager alloc] init];
}

- (void)dealloc {
[undoManager release];
[super dealloc];
}

Равноценная и противоположная реакция

Добавив экземпляр “NSUndoManager“, можно начинать выстраивать пары из действий — с равной и противоположной отменой.

Действия отмены бывают двух видов — “registerUndoWithTarget:selector:object:” и “prepareWithInvocationTarget“. Первый отправляет сообщение с одним единственным аргументом. Второй использует “NSInvocation” (применяется для хранения и пересылки сообщений между объектами) и принимает произвольное число аргументов. Наши методы “addATruck” и “removeATruck” аргументов не принимают, поэтому воспользуемся подходом с вызовом. 

Отредактируйте методы “addATruck” и “removeATruck” в файле “TallyTrucksViewController.m” (изменения выделены черным).

1
2
3
4
5
6
7
8
9
10
11
-(void)addATruck {
i += 1;
[[undoManager prepareWithInvocationTarget:self] removeATruck];
[self updateTitle];
}

-(void)removeATruck {
i -= 1;
[[undoManager prepareWithInvocationTarget:self] addATruck];
[self updateTitle];
}

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

Повтор действия

Как уже говорилось выше, “NSUndoManager” хранит список с действиями отмены. Если быть точнее, таких стеков два: один для отмены действий, а другой — для их же повторения. При отмене некоего действия изначально составлявшие его сообщения помещаются наверх стека повторов. Фактически, повтор — это отмена отмены. К счастью всем этим будет заниматься менеджер отмены действий, поэтому о подробностях можно не беспокоиться. 

Встряска

После настройки менеджера отмены действий вам, конечно же, захочется поскорее запустить приложение для проверки. Сразу предупреждаю, что рискуете глубоко разочароваться. Менеджер отмены — необходимая часть проекта, но его одного недостаточно. Его еще предстоит связать с определяющим факт встряски механизмом телефона. 

В 3.0 SDK к классу “UIApplication” добавилось булево свойство “applicationSupportsShakeToEdit“. Мы настроим его в делегате приложения. 

Отредактируйте метод “applicationDidFinishLaunching” из файла “TallyTrucksAppDelegate.m” как показано ниже (изменения выделены черным). 

1
2
3
4
5
- (void)applicationDidFinishLaunching:(UIApplication *)application {
<strong>application.applicationSupportsShakeToEdit = YES;</strong>
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

Нам потребуется обновить контроллер представления,чтобы он, во-первых, продемонстрировал готовность стать первым респондером, во-вторых, действительно стал первым респондером и, наконец, снимал с себя задачу первого респондера при скрытии представления. 

К файлу “TallyTrucksViewController.m:” добавьте методы “canBecomeFirstResponder“, “viewDidAppear:” и “viewWillDisappear:“. 

Теперь у приложения появилась функция отмены/повтора действий. После отладки запустите проект, чтобы убедиться в этом самостоятельно! (Скорее всего, приложение тестируется на симуляторе. Чтобы имитировать встряхивание, воспользуйтесь элементом “Shake” из меню файла “Hardware“).

Дорабатываем метку отмены

В нынешнем виде сообщение об отмене действия выглядит неприглядно — простые надписи “Undo” и”Redo“. Последним шагом отредактируем код так, чтобы в сообщении выводилась надпись “Undo Add A Truck” и “Redo Add A Truck“. 

Обновите метод “addATruck” из файла “TallyTrucksViewController.m” как показано ниже (изменения выделены черным):

1
2
3
4
5
6
7
8
9
10
11
12
13
-(BOOL)canBecomeFirstResponder {
return YES;
}

-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}

- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}

Заключение

Мы коснулись исключительно основ. При реализации в собственных проектах будьте внимательны: не задействуйте первый респондер надолго. Для более сложных сценариев отмены может потребоваться заключение вызовов “setActionName” в блок “if (![undoManager isUndoing])“.

Текст оригинальной статьи на английском языке [здесь]

Уважаемые читатели, данный материал был переведен и подготовлен к публикации проектом LookApp.ru, при публикации на другом сайте ссылка на LookApp.ru обязательна.

1 звезда2 звезд3 звезд4 звезд5 звезд (4 голосов, средний: 3.50 из 5)
Загрузка ... Загрузка ...


Оставьте комментарий