Following this discussion, I've encountered a bad access issue;
A loop has several steps: a, b, c, ... x, y, z:
-(void)cycle:(float)delta{
[self stepA]
[self stepB]
// etc.
[self stepZ]
}
At some point, step x does the following:
// IRQ is an NSMutableArray
// Self is a reference to the engine running the cycles
[IRQ addObject:^{ NSLog(@"hello! %@", self); } ];
Later, step z is to process all "delayed" calls:
for (int i = 0; i < [IRQ count]; i++){
void (^delayedCall)(void) = [IRQ objectAtIndex:i];
delayedCall();
}
[IRQ removeAllObjects];
Result: EXEC_BAD_ACCESS
Now, if step x only adds a plain string with no object reference like follows, step Z works fine:
[IRQ addObject:^{ NSLog(@"hello!"); } ];
Last observation, if a same step both adds blocks to the queue AND iterates over the queue to execute the blocks, then no problem occurs. Like the reference to an object gets "lost" as the step: method is left?
I don't understand much in this area and will need more help!
edit: James, just tried the following to avoid that reference cyle:
NSString *userName = @"James";
[IRQ addObject:^{ NSLog(@"hello %@", userName); } ];
and it also happens. How would your solution apply to this?
Thanks in advance!
It seems the object you pass in.. In your examples:
self
anduserName
are being prematurely deallocated. This isn't the behaviour I expect from blocks. As in my previous answer, I expected the problem to be because of too much retention!As a test, could you try:
This would be a memory leak, but it would help indicate if the object is being deallocated.
This is caused by a "retain cycle" where the block is retainingself
andself
is retaining the block.Try this:
If using ARC, use
__unsafe_unretained
instead of__block
When you create a block with the
^{}
syntax, it's created on the stack. To persist the block for a long period of time (beyond the scope of the function that creates it), you must copy the block into the heap:If using ARC, skip the
-autorelease
message.The problem is that block objects are created on the stack. You need to copy blocks to the heap when you expect them to be used after the scope in which they were declared is destroyed, and if the block is not copied for you.
Here you pass an object "down the stack" to a method that is not aware of blocks. Replace
with
and the
EXC_BAD_ACCESS
at this point will go away.In most cases though, you do not need to copy the block! A couple of examples:
-[NSArray sortedArrayUsingComparator:]
.+[UIView animateWithDuration:options:animations:completion:]
.