Как установить переменные экземпляра из NSMutableArray? - PullRequest
1 голос
/ 06 марта 2012

Итак, я нахожусь в точке, где я начинаю уменьшать код спагетти.

Итак, сейчас у меня есть 11 различных изображений динозавров, которые я поместил в NSMutableArray, используя "дляпетляЯ также объявил переменные экземпляра CCSprite, в которых я надеялся, что смогу установить для каждого изображения динозавра так, чтобы я мог проверять ограничивающие рамки, устанавливать позиции и т. Д. Поэтому я указал каждый объект из массива на переменную экземпляра.этот код:

.h файл:

CCSprite *dinosaur1_c;
CCSprite *dinosaur2_c;
CCSprite *dinosaur3_c;
CCSprite *dinosaur4_c;
CCSprite *dinosaur5_c;
CCSprite *dinosaur6_c;
CCSprite *dinosaur7_c;
CCSprite *dinosaur8_c;
CCSprite *dinosaur9_c;
CCSprite *dinosaur10_c;
CCSprite *dinosaur11_c;

.m файл

NSMutableArray *dinoSprites = [[NSMutableArray alloc] init];

for( int i = 1, j = 0; i <= 11 && j <= 10; i++, j++ )
{
    id dino = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:@"dinosaur%d-c.png", i]];
    [dinoSprites addObject:dino];
    [sceneSpriteBatchNode addChild:dino];
}


dinosaur1_c = (CCSprite *)[dinoSprites objectAtIndex:0];
dinosaur2_c = (CCSprite *)[dinoSprites objectAtIndex:1];
dinosaur3_c = (CCSprite *)[dinoSprites objectAtIndex:2];
dinosaur4_c = (CCSprite *)[dinoSprites objectAtIndex:3];
dinosaur5_c = (CCSprite *)[dinoSprites objectAtIndex:4];
dinosaur6_c = (CCSprite *)[dinoSprites objectAtIndex:5];
dinosaur7_c = (CCSprite *)[dinoSprites objectAtIndex:6];
dinosaur8_c = (CCSprite *)[dinoSprites objectAtIndex:7];
dinosaur9_c = (CCSprite *)[dinoSprites objectAtIndex:8];
dinosaur10_c = (CCSprite *)[dinoSprites objectAtIndex:9];
dinosaur11_c = (CCSprite *)[dinoSprites objectAtIndex:10];

Этот бит кода работает, но я уверен, что его можно уменьшить,Как бы я мог установить каждую из этих переменных экземпляра с помощью цикла for?

Я использую эти переменные экземпляра в других методах для установки позиций, проверки столкновений / пересечений, затухания и т. Д.

Я поместил эквивалентный код, чтобы лучше объяснить, что я пытаюсь сделать:

NSMutableArray *dinoSprites = [[NSMutableArray alloc] init];

for( int i = 1, j = 0; i <= 11 && j <= 10; i++, j++ )
{
    id dino = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:@"dinosaur%d-c.png", i]];
    [dinoSprites addObject:dino];
    [sceneSpriteBatchNode addChild:dino];

    // Set instance variables
    dinosaur%i_c = (CCSprite *)[dinoSprites objectAtIndex:j];
}

Есть ли способ достичь того, что я спрашиваю?После 2,5 часов поисков я все равно ничего не придумала.Просто нахожу решения для кадров анимации.

Я что-то упускаю или мне нужно по-разному указывать на каждое изображение в массиве, чтобы установить их позиции, плавные переходы, установить флажки и т. Д.?

Любые идеи / вклады с благодарностью!Спасибо, что нашли время, чтобы прочитать это!: D

Ответы [ 2 ]

3 голосов
/ 06 марта 2012

Вместо наличия одиннадцати CCSprite переменных экземпляра у вас должна быть только одна NSArray.

Так в вашем .h:

@property (strong) NSArray *dinoSprites;

В вашем .m, сделайте

@synthesize dinoSprites;

и затем замените код из вашего вопроса на:

NSMutableArray *newDinoSprites = [[NSMutableArray alloc] init];

for( int i = 1, j = 0; i <= 11 && j <= 10; i++, j++ )
{
    id dino = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:@"dinosaur%d-c.png", i]];
    [newDinoSprites addObject:dino];
    [sceneSpriteBatchNode addChild:dino];
}

self.dinoSprites = [newDinoSprites copy];

И затем, когда вам нужно обратиться к тому, что вы называли, скажем, dinosaur8_c, вы вместо этого просто использовали бы (CCSprite *)[dinoSprites objectAtIndex:7].

2 голосов
/ 06 марта 2012

Есть ли способ достичь того, что я спрашиваю? После 2,5 часов В поисках я еще ничего не придумала. Просто найти решение для анимационных кадров.

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

Первый способ - использовать адрес каждой переменной, то есть указатель на каждую переменную. Поскольку сами указатели являются скалярными значениями, а не объектами, вам необходимо использовать массив в стиле C:

CCSprite *ivars[] = {&dinosaur1_c, &dinosaur2_c, &dinosaur3_c, &dinosaur4_c};
for (int i = 0; i < 4; i++) {
    *(ivars[i]) = [dinoSprites objectAtIndex:i];
}

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

NSString *name;
for (int i = 0; i < [dinoSprites count]; i++) {
    name = [NSString stringWithFormat:@"dinosaur%d_c", i];
    [self setValue:[dinoSprites objectAtIndex:i] forKey:name];
}

Все это говорит: Я настоятельно рекомендую вам не использовать ни один из двух предыдущих подходов к вашей проблеме. Вполне вероятно, что есть гораздо лучшие решения вашей проблемы, которые не предусматривают наличие отдельного ивара для каждого динозавра. У вас уже есть динозавры в массиве, поэтому нет необходимости создавать отдельный ivar для каждого. Как правило, если вы когда-либо создаете пронумерованные переменные, подобные этим, вам, вероятно, следует отступить и переосмыслить то, что вы делаете - нумерация ваших переменных является сильным сигналом о том, что вы должны использовать вместо этого массив.

Итак, в вашем случае я не вижу причин, по которым вы не могли бы использовать массив, который у вас уже есть, везде в вашем коде. Вместо dinosaur6_c вы, очевидно, можете использовать [dinoSprites objectAtIndex:6]. Но вы действительно очистите свой код, если подумаете о способах обработки всех динозавров одним и тем же кодом, так что вы никогда не будете жестко кодировать конкретные признаки в своем массиве. Например, если вам нужно установить каждый динозавр в отдельную позицию, есть как минимум два хороших способа сделать это. Одним из них является вычисление позиции, если это возможно, на основе индекса. Вы можете сделать это, если вы раскладываете динозавров обычным способом, как на сетке 3 x n:

for (int i = 0; i < [dinoSprites count]; i++) {
    int row = i / DINOS_PER_ROW;
    int column = i % DINOS_PER_ROW;
    CGPoint position = CGPointMake(row * rowHeight, column * columnWidth);
    [[dinoSprites objectAtIndex:i] setPosition:position];
}

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

NSArray *positions = [NSArray arrayWithContentsOfURL:someURL]; // read positions from a property list
NSAssert([positions count] >= [dinoSprites count], @"Not enough positions!");
for (int i = 0; i < [dinoSprites count]; i++) {
    CGPoint position = [[positions objectAtIndex:i] pointValue];
    [[dinoSprites objectAtIndex:i] setPosition: position;
}

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

...