Seemingly random NSMutableArray EXC

Discussion in 'Mac Programming' started by Richard Birkett, Sep 5, 2011.

  1. Richard Birkett macrumors member

    Joined:
    Aug 21, 2011
    #1
    Hi,

    I get EXC BAD ACCESS on the the first line in move: which mentions snakeArray, an NSMutableArray, I don't have a clue what's going on. Help much appreciated.
    Code:
    //in header:
    	NSMutableArray *snakeArray;
    //in imp.:
    
    - (IBAction)start:(id)sender
    {
    	NSLog(@"1");
    	snakeArray = [NSMutableArray arrayWithObject:[NSValue valueWithRect:NSMakeRect(truncf(gridSize*gridWidth/2)+gridSpacing/2, truncf(gridSize*gridHeight/2)+gridSpacing/2, squareSize, squareSize)]];
    	theTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(move:) userInfo:nil repeats:YES];
    	NSLog(@"2");
    }
    
    - (void)move:(NSTimer *)myTimer
    {
    	NSLog(@"3%@", snakeArray); //happens here with the snake array, otherwise after "3" just below
    		//NSPoint lastSquare = [[snakeArray lastObject] rectValue].origin;
    	NSValue *lastSquare = [snakeArray lastObject];
    	NSLog(@"4");
    	NSPoint lastSquarePoint = [lastSquare rectValue].origin;
     
  2. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    So snakeArray is not a property?

    I very much recommend a programming style where you give class member variables a slightly different name, like snakeArray_ , so that all accesses stand out.

    And you shouldn't have many accesses. You should declare a "retain" property named "snakeArray" and use that; that way you take care of memory handling except for an assignment snakeArray = nil in your dealloc method.

    The crash that you have isn't really random but inevitable since the array is autoreleased.
     
  3. mydogisbox macrumors member

    Joined:
    Jan 16, 2011
    #3
    I think the problem that is you're having is with how you're creating your NSMutableArray. If you create your array with init then it is created with a retain count of 1. If you use one of the convenience methods (arrayWithObject in this case) then the object is autoreleased (released at the end of the current sequential code execution). You are using a convenience method so your NSMutableArray will be released at the end of start unless you retain it yourself (not recommended) or as gnasher729 said, you use a property that will automatically retain it for you.
     
  4. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011
    #4
    Thanks!

    Very helpful. Perhaps you could possibly help me with a small unrelated error to avoid clogging up this forum. :)

    I have this code:

    Code:
    - (void)move:(NSTimer *)myTimer
    {
    	NSPoint lastSquare = [[snakeArray lastObject] rectValue].origin;
    	switch (nextDirection) {
    		case moveUp:
    		{
    			CGRect newSquare = NSMakeRect(lastSquare.x, lastSquare.y+gridSize, squareSize, squareSize);
    			break;
    		}
    		case moveDown:
    		{
    			CGRect newSquare = NSMakeRect(lastSquare.x, lastSquare.y-gridSize, squareSize, squareSize);
    			break;
    		}
    		case moveRight:
    		{
    			CGRect newSquare = NSMakeRect(lastSquare.x+gridSize, lastSquare.y, squareSize, squareSize);
    			break;
    		}
    		case moveLeft:
    		{
    			CGRect newSquare = NSMakeRect(lastSquare.x-gridSize, lastSquare.y, squareSize, squareSize);
    			break;
    		}
    	}
    	[snakeArray addObject:[NSValue valueWithRect:newSquare]];
    	currentDirection = nextDirection;
    	[self setNeedsDisplay:YES];
    }
    Firstly you'll notice the {} after each case, for some reason, it wouldn't accept the declaration, then break but had been accepting a message and then break :S... but now it error saying newSquare is an undeclared identifier after the switch!!!
     
  5. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #5
    Declare newSquare once before the switch. Assign to it inside your cases. The {} in a case is odd and unnecessary.

    -Lee
     
  6. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #6
    The error was that he was redeclaring newSquare repeatedly within the same scope (in each case statement). Scoping newSquare in the case statements made that error go away but took newSquare out of scope of the enclosing method. Personally, I prefer to declare everything at the very beginning of a method or function, this scattering of declarations throughout code looks sloppy and wrong. (I also like to order my declarations by size, to possibly conserve stack space, but that is just me being AR.)
     
  7. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011

Share This Page