Вложенные массивы в Objective-C (NSMutableArray) - PullRequest
3 голосов
/ 07 августа 2009

Я пытаюсь создать вложенный массив. Сначала я создаю массив PlayerItems, который будет содержать 10 массивов, каждый из которых содержит объекты предметов, соответствующие инвентарям каждого игрока в игре. В указанной строке я получаю следующую ошибку:

ошибка: значение void не игнорируется, как должно быть

Какое значение здесь void? Если я использовал [[PlayerItems objectAtIndex:i] addObject:myitem], программа компилируется, но вылетает. Если я прокомментирую эту строку, она компилируется и запускается нормально. Спасибо за вашу помощь!

self.PlayerItems = [[NSMutableArray alloc] initWithCapacity:11];
NSMutableArray *itemarray = [[NSMutableArray alloc] initWithCapacity:60];
item *myitem = [[item alloc] init];
item.kind = 1;
for (int i = 1; i < 10; i++) {
    itemarray = [[NSMutableArray alloc] initWithCapacity:60];
    [PlayerItems addObject:itemarray];
    for (int i2 = 1; i2 < 50; i2++) {
        myitem = [[item alloc] init];
        myitem.kind = 1;
        // The error occurs on the line below:
        ((NSMutableArray *) [[PlayerItems objectAtIndex:i] addObject:myitem]);
    }
}

Ответы [ 4 ]

8 голосов
/ 07 августа 2009

Я бы сделал это следующим образом:

self.playerItems = [[NSMutableArray alloc] initWithCapacity:11];

NSMutableArray * itemArray;
Item * anItem;
for (int playerIndex = 1; playerIndex <= 10; playerIndex++)
{
    itemArray = [NSMutableArray arrayWithCapacity:60];
    [playerItems addObject:itemArray];

    for (int itemIndex = 1; itemIndex <= 50; itemIndex++)
    {
        anItem = [[Item alloc] init];
        anItem.kind = 1;
        [itemArray addObject:anItem];
        [anItem release];
    }
}

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

Обновление:

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

Player.h

@interface Player : NSObject
{
    NSMutableArray * items;
}
@property (readonly) NSMutableArray * items;
@end

Player.m

#import "Player.h"
@implementation Player

@synthesize items;

- (id)init
{
    if ((self = [super init]) == nil) { return nil; }

    items = [[NSMutableArray alloc] initWithCapacity:60];
    Item * anItem;
    for (int itemIndex = 1; itemIndex <= 50; itemIndex++)
    {
        anItem = [[Item alloc] init];
        anItem.kind = 1;
        [items addObject:anItem];
        [anItem release];
    }

    return self;
}

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

@end

В других местах

NSMutableArray * allPlayers = [[NSMutableArray alloc] initWithCapacity:11];

Player * aPlayer;
for (int playerIndex = 1; playerIndex <= 10; playerIndex++)
{
    aPlayer = [[Player alloc] init];
    [allPlayers addObject:aPlayer];
    [aPlayer release];
}

...

[allPlayers release];
5 голосов
/ 07 августа 2009

Привет, я пытаюсь создать вложенный массив ...

Не делай этого. Параллельные и вложенные массивы труднее писать и читать, чем реальные объектно-ориентированные решения, подобные предлагаемому eJames, то есть созданию класса модели.

Рассмотрим код для установки вида предмета первого предмета каждого игрока. С параллельными / вложенными массивами:

for (NSArray *items in PlayerItems)
    [[items objectAtIndex:0U] setKind:newKind];

С объектами модели:

for (Player *player in players)
    [player setKind:newKind];

Какой из них яснее?

Работа, необходимая для поддержки параллельных и вложенных массивов, для синхронизации их всех при каждом изменении и доступа к любому элементу в них, намного больше, чем работа, необходимая для создания класса модели. Кроме того, если вы решите портировать на Mac, отсутствие классовой модели активно причиняет вам боль, поскольку вы не можете использовать Bindings, а реализация поддержки AppleScript (не большая проблема для игры, я признаю) практически невозможна.

Как уже упоминал eJames, вы обильно пропускаете объекты. Следуйте его рекомендациям и прочитайте Руководство по программированию управления памятью для какао.

Как сказал pgb, индексы массивов в Какао (и C, в этом отношении) начинаются с 0. Более того, вы, как правило, не используете индексы без необходимости; см. мои примеры кода выше для более ясного способа итерации в массиве.

Как указывают pgb и Christian, addObject: - это метод, который возвращает void, который вы затем приводите к NSMutableArray *. Возможно, вы хотели поместить этот бросок в первую пару квадратных скобок? Но это еще одна проблема, с которой вы бы не столкнулись, если бы у вас был реальный класс модели, поскольку вы настраивали бы все сразу для нового игрока, включая его предметы:

Player *player = [[Player alloc] init];

//Set up name, SPECIAL stats, etc.

for (int kind = 1; kind < 50; ++kind) {
    Item *item = [[Item alloc] init]; //I capitalized your class name for you.
    [item setKind:kind];
    [player addInventoryObject:item]; //Assume “inventory” is the name of the property that holds the player's items.
    [item release];
}

[allPlayers addObject:player];
[player release];

Это подводит меня к еще одному предложению: вы также можете создать класс модели для типов элементов и иметь их где-нибудь. Тогда каждый вид может иметь имя, значок, возможно, описание, природу, такую ​​как одноручное или двуручное, требования к классу, требования к статистике и т. Д., Прямо в объекте типа элемента. Цикл выглядит следующим образом:

for (ItemKind *kind in [self kindsOfItems]) {
    Item *item = [[Item alloc] initWithKind:kind];
    [player addInventoryObject:item];
    [item release];
}

Кроме того, если вы расширяете это свойство kindsOfItems, вы можете позволить игрокам добавлять больше видов предметов позже, либо через подключаемые модули (Mac), либо через приложения для покупок (iPhone).

1 голос
/ 07 августа 2009

В последней строке вы звоните addObject: , которая возвращает void:

- (void)addObject:(id)anObject

Затем вы пытаетесь привести void к NSMutableArray *. И вы также никому не назначаете брошенную пустоту.

Чтобы добавить подмассив в ваш массив, этого должно быть достаточно:

[[PlayerItems objectAtIndex:i] addObject:myitem];

Кстати: вы создаете только 9 массивов и добавляете только 49 подмассивов.

1 голос
/ 07 августа 2009

Массивы в Objective-C начинаются с нуля, а цикл for начинается с 1. Вы должны изменить его на

for (int i = 0; i < 10; i++)

Что касается ошибки void, вам не нужно приводить возвращаемое значение addObject:, поскольку оно возвращает void, поэтому вы получаете предупреждение.

Эта строка должна гласить:

[[PlayerItems objectAtIndex:i] addObject:myitem];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...