ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 3

Приступая к работе

Недавно я писал урок о обработке касаний в iOS. Это хороший способ внести изменения в приложение. Давайте попробуем проделать то же самое в Cocos2D. Я предлагаю далеко не ходить и воспользоваться примером Cocos2D HelloWorld, попутно внося в него изменения:

 

<code data-result="[object Object]">-(id) init
{
	if( (self=[super init])) {
		CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello World" 
                                               fontName:@"Marker Felt" 
                                               fontSize:64];
		CGSize size = [[CCDirector sharedDirector] winSize];
		label.position =  ccp( size.width /2 , size.height/2 );
		[self addChild: label];

		//Установка метки
		label.tag = 8;
	}
	return self;
}</code>

 

В этом коде, кроме привычного добавления надписи на дисплей, мы установили ей метку. Это свойство любого элемента интерфейса, а принимает оно целочисленное значение. Для чего мы это сделали? В уроке Управление памятью в Cocos2D я говорил, о том как можно позднее получить доступ к дочернему объекту вашего класса (вы можете обратиться к нему по тегу). Тег задается совершенно произвольно, за исключением того, что он должен быть положительным числом, и каждый объект должен иметь свой собственный уникальный тег. Вы не можете создать два обьекта с одинаковыми тегами. И здесь есть очень важный момент. По умолчанию у всех объектов тег равен нулю. То есть, если вы захотите установить какому-то своему объекту интерфейса тег ноль — получить к нему доступ уже не удастся.

 

Совет: Вместо того чтобы использовать магические числа (например, как 8) для обозначения тегов, следует взять за правило определять дэфайны для работы с тегами. В дальнейшем Вы с трудом вспомните, что означает такой тег, как число 8, по сравнению с написанием значимых имен дэфайна (например, kTagForLabel). О том как это делается можно почитать в соответствующем уроке Чистка кода (#define, Refactor).

 

Кроме того, не забываем о свойстве isTouchEnabled, который выполняет ту же функцию, что и userInteractionEnabled подробно расписаном в обработке касаний. Только после этого можно вызывать метод ccTouchesBegan:

 

<code data-result="[object Object]">-(void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    CCLabelTTF* label = (CCLabelTTF*)[self getChildByTag:8]; 
    label.scale = CCRANDOM_0_1(); 
}</code>

 

С помощью [self getChildByTag: 8], можно получить доступ к CCLabelTTF объекта по его тегу, которое вы назначили в методе инициализации. В этом случае мы используем удобный в Cocos2D CCRANDOM_0_1 (), чтобы изменить размер label значение между 0 и 1. Это позволит изменять размер label при каждом касании экрана.

 

Мотод getChildByTag всегда возвращает надпись, можно смело привести его к (CCLabelTTF *) типу. Однако, вы должны знать, что может произойти сбой игры, если полученный объект не является производным от класса CCLabelTTF по некоторым причинам. Это вполне может произойти, если вы случайно дадите другому объекту такое же значение тега, как например 8. По этой причине можно использовать защитный стиль программирования и убедиться, что вы работаете с тем, что требуется. Защищенное программирования использует проверку, убеждаясь, что сделанные предположения верны. Для этого вы должны использовать метод NSAssert:

 

<code data-result="[object Object]">-(void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    CCNode* node = [self getChildByTag:8]; 

    //Проверка, что возвращенный node является CCLabelTTF  
    NSAssert([node isKindOfClass:[CCLabelTTF class]], @"node is not a CCLabelTTF!");
    CCLabelTTF* label = (CCLabelTTF*)node; 
    label.scale = CCRANDOM_0_1(); 
}</code>

 

В этом случае мы ожидаем, что узел возвращает getChildByTag объект, производный от CCLabelTTF, но мы никогда не можем быть уверены в этом на 100% не используя NSAssert, плюс это может помочь в поиске ошибок, прежде чем они приведут к аварийному завершению приложения.

 

Отметим, что данная проверка добавляет еще две строки кода, но с точки зрения производительности все остаюется неизменным. Вызов NSAssert полностью удаляется в версии Release builds, CCLabelTTF * label = (CCLabelTTF *) node; то, что мы уже сделали, только на одной линии. По существу, обе версии выполняют одно и тоже, но во втором случае вы видите уведомления, если вы не получите ожидаемого объекта CCLabelTTF, а сбой с EXC_BAD_ACCESS ошибкой.

Comments are closed.