Question

__block BOOL myBool = NO;
__strong MyClass *ptr = self;
self.footer.defaultSelectedItem.selectionBlock = ^{
    myBool = YES;
    ptr = nil;
};

This works just fine when my Scheme's Build Configuration is set to Debug, but I get an EXC_BAD_ACCESS when I run with Release. The EXC_BAD_ACCESS happens on the the following line

if(selectionBlock != nil) selectionBlock();

but if I comment out all the lines inside my selectionBlock then it runs with no error. Why does this run in Debug and not Release?

FYI I'm using Automatic Reference Counting (arc)

** EDIT in response to @RobNapier **

The original code that works in debug is:

__block BOOL flag = NO;
__strong EventsView *ptr = self;
self.footer.defaultSelectedItem.selectionBlock = ^{
    if(flag) return;
    flag = YES;
    [ptr backTUI:nil];
    flag = NO;
};
Was it helpful?

Solution 2

For the life of me I could not get this to work with a block. So instead I moved to using a setter for the Event View pointer. I'm guessing that fixed the problem with my pointer by setting up an additional ARC retain. I'm still uncertain because I never saw a zombie get logged when using the block so yeah.

When in doubt, use a selector.

OTHER TIPS

There's no reason for the extra ptr here. Using self inside the block would be more correct. The block will retain self in that case. That may cause a retain loop, so it's up to you to remember to set self.selectionBlock = nil at some point before dealloc to break the retain loop.

flag may be optimized away here. It's not clear how it could possibly be useful from the above code.

I'm always very nervous about long indirection-chains in a set operation like this one:

self.footer.defaultSelectedItem.selectionBlock = ...

I would make sure that footer, and the current defaultSelectedItem can't disappear before this runs.

Simplify the problem. Make the block just log "Running block." Then add back things until it crashes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top