BlackMouse
BlackMouse

Reputation: 4552

Block inside block = EXC_BAD_ACCESS

I have a singleton class the handle all the Game Center logic:

typedef void (^GameCenterCallbackFinishUpdating)();

- (void)getAllMatches:(GameCenterCallbackFinishUpdating)onComplete
{
    [GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
    {      
        //Do stuff here... 
        onComplete();
    }];
}

From another viewController I use:

[[GameCenterHelper sharedHelper] getAllMatches:^{

    [self.myTableView reloadData]; 

}];

It works great when I'm in the app, but once I close the app (background) and then start it up again, I get:

    onComplete();     ---- Thread 1: EXC_BAD_ACCESS (code=2, address=0xc)

What am I doing wrong here?

Upvotes: 3

Views: 3560

Answers (2)

Muhammad Umair
Muhammad Umair

Reputation: 1714

Thanks to @holex and @Paul.s for explaining it well. I had the similar situation where I was sending block as method parameter(completionHandler).

- (void)callX:(NSString *)xyz withCompletionHandler:(void (^)(NSString *response))completion
{
    completion(something);
}

And there are two situations either I am using this block like:

[MyClass sharedInstance] callX:@"abc" withCompletionHandler:^(NSString *response) {
    if (response) {
        //do something
    }
}];

or this block could be nil as method parameter:

[MyClass sharedInstance] callX:@"abc" withCompletionHandler:nil];

In second case when block was being passed nil as method parameter this caused EXC_BAD_ACCESS on completion(). So as @holex states that the blocks are objects and if any block is nil and you try to call them, it crashes the application. A single if saves lot of my time

- (void)callX:(NSString *)xyz withCompletionHandler:(void (^)(NSString *response))completion
{
    if (completion)
        completion(something);
}

P.S: this explanation only for NERDS like me. | ' L ' |

Upvotes: 0

holex
holex

Reputation: 24041

some background info: the blocks are objects and if any block is nil and you try to call them, it crashes the application.

somewhere and somehow the block onComplete becomes nil before you call it. the following if (...) statement helps you to prevent to call a nil pointer, so the application won't crash.

if (onComplete) onComplete();

Upvotes: 10

Related Questions