views:

433

answers:

2

Hi there,

I've got a code snippet here that I can't make working.

NSUInteger i;
//NSMutableArray *textures = [[NSMutableArray alloc] initWithCapacity:kNumTextures];
//NSMutableArray *texturesHighlighted = [[NSMutableArray alloc] initWithCapacity:kNumTextures];

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


for (i = 1; i <= kNumTextures; i++)
{
    NSString *imageName = [NSString stringWithFormat:@"texture%d.png", i];
    NSString *imageNameHighlighted = [NSString stringWithFormat:@"texture%d_select.png", i];
    UIImage *image = [UIImage imageNamed:imageName];
    UIImage *imageHighlighted = [UIImage imageNamed:imageNameHighlighted];
    //NSArray *pics = [[NSArray alloc] initWithObjects:(UIImage)image,(UIImage)imageHighlighted,nil];
    NSArray *pics = [NSArray arrayWithObjects:image,imageHighlighted,nil];
    [textures addObject:pics];
    [pics release];
}

//select randomly the position of the picture that will be represented twice on the board
NSInteger randomTexture = arc4random()%([textures count]+1);

//extract image corresponding to the randomly selected index
//remove corresponding pictures from textures array
NSArray *coupleTexture = [textures objectAtIndex:randomTexture];
[textures removeObjectAtIndex:randomTexture];

//create the image array containing 1 couple + all other pictures
NSMutableArray *texturesBoard = [[NSMutableArray alloc] initWithCapacity:kNumPotatoes];

[texturesBoard addObject:coupleTexture];
[texturesBoard addObject:coupleTexture];
[coupleTexture release];

NSArray *pics = [[NSArray alloc] init];
for (pics in textures)  {
    [texturesBoard addObject:pics];
}
[pics release];

//shuffle the textures
//[texturesBoard shuffledMutableArray];

//Array with masks
NSMutableArray *masks= [[NSMutableArray alloc] init];

for (i = 1; i <= kNumMasks; i++)
{
    NSString *maskName = [NSString stringWithFormat:@"mask%d.png", i];
    UIImage *mask = [UIImage imageNamed:maskName];
    //NSArray *pics = [[NSArray alloc] initWithObjects:mask,nil];
    [masks addObject:mask];

    //[pics release];
    [maskName release];
    [mask release];
}

//Now mask all images in texturesBoard
NSMutableArray *list = [[NSMutableArray alloc] init];
for (i = 0; i <= kNumMasks-1; i++)
{
    //take on image couple from textures
    NSArray *imgArray = [texturesBoard objectAtIndex:i];
    UIImage *mask = [masks objectAtIndex:i];

    //mask it with the mask un the array at corresponding index
    UIImage *img1 =(UIImage *) [imgArray objectAtIndex:0];
    UIImage *img2 =(UIImage *) [imgArray objectAtIndex:1];
    UIImage *picsMasked = [self maskImage:(UIImage *)img1 withMask:(UIImage *)mask];
    UIImage *picsHighlightedMasked = [self maskImage:(UIImage *)img2 withMask:(UIImage *)mask];
    //Init image with highlighted status
    TapDetectingImageView *imageView = [[TapDetectingImageView alloc] initWithImage:picsMasked imageHighlighted:picsHighlightedMasked];
    [list addObject:imageView];
}

The problem here is that : img1 and img2, are not images but rather NSArray with multiple entries. Ican't figure why... dos any fresh spirit here could provide me with some clue to fix.

maaany thanks.

A: 

This code gave me a headache. You really need to clean this up and encapsulate in some methods or functions, especially if you insist on reassigning the same variable names over and over again.

I think your problem is here:

NSArray *pics = [[NSArray alloc] init];
for (pics in textures)  {
    [texturesBoard addObject:pics];
}
[pics release];

First you assign an initialized by empty array, then you assign it the arrays in textures then you release the last array you assigned. It think that is scrambling the texturesBoard array. It most likely kills one of the arrays making the array size come out wrong.

It should just be:

NSArray *pics;
for (pics in textures)  {
    [texturesBoard addObject:pics];
}
TechZen
+1  A: 

Lets start with a memory issue in the first for loop. There's an overrelease:

NSArray *pics = [NSArray arrayWithObjects:image,imageHighlighted,nil];
[textures addObject:pics];
[pics release];   // <-- pics is overreleased since it is created autoreleased

Second memory issue. coupleTexture is overreleased.

NSArray *coupleTexture = [textures objectAtIndex:randomTexture];
[textures removeObjectAtIndex:randomTexture];

//create the image array containing 1 couple + all other pictures
NSMutableArray *texturesBoard = [[NSMutableArray alloc] initWithCapacity:kNumPotatoes];

[texturesBoard addObject:coupleTexture];
[texturesBoard addObject:coupleTexture];
[coupleTexture release];      // <--- coupleTexture is autoreleased since it is returned by objectAtIndex: and not retained

The you should learn how to do fast enumerations. It should look like this:

for (NSArray *pics in textures)  {
    [texturesBoard addObject:pics];
}

More memory issue in the masks for loop:

NSString *maskName = [NSString stringWithFormat:@"mask%d.png", i];
UIImage *mask = [UIImage imageNamed:maskName];
//NSArray *pics = [[NSArray alloc] initWithObjects:mask,nil];
[masks addObject:mask];

//[pics release];
[maskName release];     // <-- overreleased.. was created by stringWithFormat
[mask release];         // <-- overreleased.. same same

Therefore the masks array isn't released... as well as the list array created right after the loop...

Oh boy. Here I have to stop since I also start getting headaches ;) Things you should learn:

  • Only release what you created via init or what you retained explicitly
  • Use fast enumeration in the right way
  • Structure your code... Maybe extract some of the for loops to separate methods and debug their results separate.

Don't get frustrated. Keep on learning :)

stigi
thanks a lot for the answer and really sorry for the headaches ... I'll use your advice and clean that stuff.cheers.
Tibi