views:

31

answers:

2

I have a Cocos2D iPhone application that requires a set of CGRects overlaid on an image to detect touches within them. "Data" below is a class that holds values parsed from an XML file. "delegateEntries" is a NSMutableArray that contains several "data" objects, pulled from another NSMutableArray called "entries" that lives in the application delegate.

For some strange reason, I can get at these values without problems in the init function, but further down the class in question, I try to get at these values, and the application crashes without an error message (as an example, I put in the "ccTouchBegan" method which accessess this data through the "populateFieldsForTouchedItem" method).

Can anyone see why these values would not be accessible from other methods? No objects get released until dealloc. Thanks in advance!

@synthesize clicked, delegate, data, image, blurImage, normalImage, arrayOfRects, delegateEntries;
- (id)initWithTexture:(CCTexture2D *)aTexture {

    if( (self=[super initWithTexture:aTexture] )) {
        arrayOfRects = [[NSMutableArray alloc] init];
        delegateEntries = [[NSMutableArray alloc] init];
        delegate = (InteractivePIAppDelegate *)[[UIApplication sharedApplication] delegate];
        delegateEntries = [delegate entries];
        data = [delegateEntries objectAtIndex:0];
        NSLog(@"Assigning %@", [[delegateEntries objectAtIndex:0] backgroundImage]);
        NSLog(@"%@ is the string", [[data sections] objectAtIndex:0]);
        //CGRect rect;
        NSLog(@"Count of array is %i", [delegateEntries count]);

        //collect as many items as there are XML entries
        for(int i=0; i<[delegateEntries count]; i++) {
            if([[delegateEntries objectAtIndex:i] xPos]) {
                NSLog(@"Found %i items", i+1);
                [arrayOfRects addObject:[NSValue valueWithCGRect:CGRectMake([[[delegateEntries objectAtIndex:i] xPos] floatValue], [[[delegateEntries objectAtIndex:i] yPos] floatValue], [[[delegateEntries objectAtIndex:i] xBounds] floatValue], [[[delegateEntries objectAtIndex:i] yBounds] floatValue])]];
            } else {
                NSLog(@"Nothing");
            }
        }
        blurImage = [[NSString alloc] initWithString:[data backgroundBlur]];
        NSLog(@"5");
        normalImage = [[NSString alloc] initWithString:[data backgroundImage]];
        clicked = NO;
    }
    return self;    
}

And then:

- (void)populateFieldsForTouchedItem:(TouchedRect)touchInfo
{
    Data *touchDatum = [[Data alloc] init];
    touchDatum = [[self delegateEntries] objectAtIndex:touchInfo.recordNumber];
    NSLog(@"Assigning %@", [[[self delegateEntries] objectAtIndex:touchInfo.recordNumber] backgroundImage]);
    rect = [[arrayOfRects objectAtIndex:touchInfo.recordNumber] CGRectValue];
    image = [[NSString alloc] initWithString:[[touchDatum sections] objectAtIndex:0]];
    [touchDatum release];
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    TouchedRect touchInfo = [self containsTouchLocation:touch];
    NSLog(@"Information pertains to %i", touchInfo.recordNumber);
    if ( !touchInfo.touched && !clicked ) {  //needed since the touch location changes when zoomed
        NSLog(@"NOPE");
        return NO;
    }
    [self populateFieldsForTouchedItem:touchInfo];
    NSLog(@"YEP");
    return YES;
}
+2  A: 

Change this...

delegateEntries = [[NSMutableArray alloc] init]; delegateEntries = [delegate entries];

To this...

delegateEntries = [[delegate entries] copy];

You are currently leaking memory. Release delegateEntries when done.

Dylan Copeland
Sharing the delegate's NSMutableArray is still probably not a good idea. It's dangerous for two objects to share mutable state.
Chuck
Thank you Dylan, for the insight. I ended up using Chuck's solution, above, but thank you for pointing that out. Had I enough reputation, I'd vote both of you up.
diatrevolo
+1  A: 

It isn't an array that holds values pulled from the delegate's entries — it is the exact same array. You're assigning delegateEntries to point to the delegate's entries array. This means that if the delegate releases its array, you're accessing a freed object and you get the result you're seeing. If you want a copy of the delegate's array, do [[delegate entries] mutableCopy].

Incidentally, the delegateEntries = [[NSMutableArray alloc] init] assignment is just a memory leak if you're doing to immediately assign the variable to point to the delegate's array. You're creating an array on that line, never releasing it and just forgetting about it in the next step.

Chuck
Thank you Chuck! A combination of this and retaining "touchDatum" after ccTouchBegan runs solved my problem it seems. I shall test further to make sure, but looks good. Thanks for the insight!
diatrevolo