views:

357

answers:

2

Hey Guys,

I have what I think is a weird error but of course i'm relatively new to iPhone Development so it's possible that it's not all that weird after all.

I have an array (NSMutableArray) of objects that I am keeping track of (one is added to the array every time the user touches a button) what I'm trying to do is when the array reaches a certain value I add the new object to the beginning of the array and then remove the last object in the array. When I step through my code everything works the object is removed but then the app just crashes...the debugger isn't on any line of code when the app crashes and there are no loops or timers in the app yet so I can't think of anything else that is running.

here is the code that is executed right before the crash

if([objectArray count] > 10)
{
 MyObject *objectToRemove = [[MyObject alloc] init];
 objectToRemove = [objectArray objectAtIndex:10];
 [objectArray removeObjectAtIndex:10];
 [objectToRemove removeFromSuperview];
}

the main point of this code is that everytime the user touches a button an object is added to the screen and displayed, and then when the number of objects reaches 10 and the user touches the button again the first object that was added is removed and the new object is displayed. If I comment out the removeObjectAtIndex line everything works as intended but the array continues to grow.

I've also tried removing the object after the UIview is removed and the app behaves the same way. If I try to remove an object from the array at a different index (I.E 3) the app doesn't crash but it doesn't give me my expected result. but like I said the code runs fine and when I check the count of the array before and after the execution of the line the value is 11 and 10 respectively.

Any help you can provide would be appreciated,

BWC

+5  A: 

I don't think this does what you think it does. Going line by line:

MyObject *objectToRemove = [[MyObject alloc] init];

You allocate a new object of type "MyObject.

objectToRemove = [objectArray objectAtIndex:10];

You overwrite your local MyObject pointer with whatever was at index 10 in objectArray. The objectToRemove that you initially allocated is now leaked.

 [objectArray removeObjectAtIndex:10];

Now you've removed the object at index 10. When you remove it from the array, it is released and its reference count is decremented. This may (or may not) cause it to be deallocated.

 [objectToRemove removeFromSuperview];

Now you are sending a message to the object that was previously in the objectArray. If the object was deallocated by the previous line of code, I would expect a crash.

Putting aside the leak in the declaration, you might be able to do this:

        objectToRemove = [[objectArray objectAtIndex:10] retain];
        [objectArray removeObjectAtIndex:10];
        [objectToRemove removeFromSuperview];
        [objectToRemove release];

This would prevent the object from being deallocated out from under you, if that's why the crash is happening.

One way to determine if my scenario is what is happening is to turn on NSZombies, which you can do by setting the environment variable NSZombieEnabled to YES.

peterb
+1  A: 

How about:

MyObject *objectToRemove = [objectArray objectAtIndex:10];
[objectToRemove removeFromSuperview];
[objectArray removeObjectAtIndex:10];

removeFromSuperview will decrement the retain count once on objectToRemove. (removeFromSuperview implies that it was added to the view previously and that had retained it and incremented its retain count by one). removeObjectAtIndex will decrement it again. But in this order, you most likely will not be releasing it when you still need it around. (Of course, adding to the array also retained it so the order may not be that important).

mahboudz