3

我有一个单例类来处理所有游戏中心逻辑:

typedef void (^GameCenterCallbackFinishUpdating)();

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

从我使用的另一个视图控制器:

[[GameCenterHelper sharedHelper] getAllMatches:^{

    [self.myTableView reloadData]; 

}];

当我在应用程序中时效果很好,但是一旦我关闭应用程序(后台)然后再次启动它,我会得到:

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

我在这里做错了什么?

4

2 回答 2

10

一些背景信息:块是对象,如果有任何块 nil 并且您尝试调用它们,它会使应用程序崩溃。

在你调用它之前,某个地方以某种方式onComplete变成了块。nil以下if (...)语句可帮助您防止调用nil指针,因此应用程序不会崩溃。

if (onComplete) onComplete();
于 2013-01-11T15:25:39.513 回答
0

感谢@holex 和@Paul.s 很好地解释了它。我有类似的情况,我将块作为方法参数(completionHandler)发送。

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

我使用这个块有两种情况,比如:

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

或者这个块可以nil作为方法参数:

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

在第二种情况下,当块作为方法参数传递时,nil这会导致completion()。因此,@holex 声明块是对象,如果任何块为 nil 并且您尝试调用它们,它会使应用程序崩溃。 一个 if 节省了我很多时间EXC_BAD_ACCESS

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

PS:这个解释只针对NERDS像我这样的人。| 'L' |

于 2016-04-15T10:01:31.453 回答