+3  A: 

First, if you have a crash, you have a backtrace. Always provide the backtrace with your question (it'll be in the debugger and can be copy/pasted).

As Vojito implied, the most common cause of crashes like these is related to the over-releasing of objects.

In your case, for(;;) and for(... in ...) are not actually exactly the same. The latter is very likely causing the objects within the array to be retained for the duration of iteration or autoreleased upon retrieval (I say "very likely" because I didn't test it -- but it would explain the behavior).

In your code, you are modifying your object graph during iteration with statements like otherBody = contact.bodyB. If any one of those statements happens to cause one of the items in the array being iterated to be released out from under the array, you would see a crash. Similarly, if the modification of the object graph causes either contact.bodyA or contact.bodyB to become a dangling reference, you would see a crash.

All just an educated guess. Post the backtrace and, as Vojito suggested, run under the Allocation instrument in Instruments with zombie detection enabled.

bbum
Hmm, thanks, this sounds like it could be it. Seems I've still got a whole lot to learn about memory management! I come from a C# background, so typically I'm used to all this stuff being taken care of for free. It's interesting, but hard work!
AlexC
+1  A: 

Stack variables, including object references, will not automatically initialize to nil/0/NULL. Try setting otherBody to nil in its initializer:

PhysicsBody *otherBody = nil;

If the debugger is saying that the le assignment is where the exception occurs, it actually may be the statement above it, i.e. [otherBody userData]. Without initializing it, otherBody is a garbage value.

Jason
While it's definitely true he should initialize otherBody to nil, he doesn't in both the one that works and the one that doesn't work, meaning that (somehow) doesn't seem to be causing the crash, unless NSFastEnumeration wonks with the stack (which I do not believe it does)
Jared P
Good point, thanks. As Jared P stated, I don't believe this is causing the crash, although as you have said, it is, as a general rule, good practice. Thanks :)
AlexC
Since NSFastEnumeration is involved, it means that the stacks are completely different between the two examples. So, in one instance otherBody (due to calling semantics) may never be garbage and actually start out with a nil value. @AlexChilcott, did you try my suggestion? From your comments, it doesn't look like you've investigated if this fixes it (or the accepted answer's proposal).
Jason
Hi Jason. Thanks for your suggestion :) I did make the change suggested in your answer, just in case it was true that neither assignment of otherBody was hit (which should not be the case, as it is covered by an assert elsewhere in my code). However, it did not fix my problem. I accepted bbum's answer because it gives a reasonable explanation (that I can not yet rule out) as to why I am seeing the behaviour that I am. I have not yet got to the bottom of it, so am not able to say for sure what is going on, but bbum's answer was the most enlightening.
AlexC
Is your app threaded at all?
Jason
Nope, all logic is on the same thread. It's a pretty simple app really, just something to get me started with Obj C and iPhone.
AlexC