Question

I'm trying to build a nested array: First, I make a "PlayerItems" array which will contain 10 arrays, each containing item objects, corresponding to the inventories of each player in the game. On the indicated line, I get the following error:

error: void valued not ignored as it ought to be

What is the void value here? If I used [[PlayerItems objectAtIndex:i] addObject:myitem] instead, the program compiles but crashes. If I comment that line out, it compiles and runs OK. Thank you for your help!

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]);
    }
}
Was it helpful?

Solution

I would do it as follows:

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];
    }
}

As a side note, you should definitely read up on memory management in Cocoa, since your original code is full of memory leaks. It can be a bit difficult to wrap your head around at first, but once you learn it, it becomes second nature. Well worth the effort.

update:

A more object-oriented way to do this would be to create a Player class, and have each Player manage its own set of items:

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

Elsewhere

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];

OTHER TIPS

Hi, I'm trying to build a nested array…

Don't do that. Parallel and nested arrays are harder to write and to read than real object-oriented solutions like the one eJames suggested, which is that of creating a model class.

Consider the code to set the item kind of every player's first item. With parallel/nested arrays:

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

With model objects:

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

Which one is clearer?

The work required to maintain parallel and nested arrays, to keep them all synchronized for every change and to access any item in them, is far greater than the work required to create a model class. Additionally, if you decide to port to the Mac, not having a model class actively hurts you, as you can't use Bindings and implementing AppleScript support (not such a big deal for a game, I admit) is next to impossible.

As eJames also mentioned, you are leaking objects profusely. Follow his recommendation and read the Memory Management Programming Guide for Cocoa.

As pgb said, array indexes in Cocoa (and C, for that matter) start at 0. Moreover, you generally don't use indexes unless you have to; see my code examples above for a much clearer way to iterate on an array.

As pgb and Christian both point out, addObject: is the method that returns void, which you then cast to NSMutableArray *. Perhaps you meant to put that cast inside the first pair of square-brackets? But this is another problem you wouldn't have if you had a real model class, as you would be setting up everything about the new Player at once, including his items:

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];

This brings me to one more suggestion: You might also want to make a model class for the item kinds, and have an array of those somewhere. Then, each kind can have a name, an icon, perhaps a description, nature such as one-handed vs. two-handed, class requirements, stat requirements, etc., all right there in the item-kind object. The loop then looks like this:

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

Additionally, if you design this kindsOfItems property extensibly, you can allow players to add more item kinds later, either through plug-ins (Mac) or in-app purchasing (iPhone).

The arrays in Objective-C are zero based, and your for loop is starting in 1. You should change it to

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

As for the void error, you don't need to cast the return value of addObject: since it returns void, that's why you are getting the warning.

That line should read:

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

In the last line you're calling addObject: which returns void:

- (void)addObject:(id)anObject

You then try to cast void to NSMutableArray*. And you also don't assign the casted void to anything.

To add the subarray to your array this should be sufficient:

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

BTW: You're creating only 9 arrays and you're adding only 49 subarrays.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top