为什么发布通知会导致崩溃?

时间:2013-11-18 12:05:18

标签: ios objective-c game-center gamekit nsnotificationcenter

我使用以下代码发布通知,但它与EXC_BAD_ACCESS崩溃:

[[NSNotificationCenter defaultCenter]postNotificationName:AUTHENTICATED_NOTIFICATION object:nil];

在我的constants.h文件中:

#import <Foundation/Foundation.h>

extern NSString *const PLAYER_ID;
extern NSString *const RANDOM_NUMBER;

extern NSString *const AUTHENTICATED_NOTIFICATION;
extern NSString *const UNAUTHENTICATED_NOTIFICATION;

@interface RIYConstants : NSObject
{

}

@end

在我的constants.m文件中

#import "RIYConstants.h"

NSString *const PLAYER_ID = @"playerId";
NSString *const RANDOM_NUMBER = @"randomNumber";

NSString *const AUTHENTICATED_NOTIFICATION = @"AUTHENTICATED_NOTIFICATION";
NSString *const UNAUTHENTICATED_NOTIFICATION = @"UNAUTHENTICATED_NOTIFICATION";

@implementation RIYConstants

@end

崩溃的方法是在游戏中心验证时调用的处理程序:

-(void)authenticatedPlayer:(GKLocalPlayer*)localPlayer
{
    [[NSNotificationCenter defaultCenter]postNotificationName:AUTHENTICATED_NOTIFICATION object:nil];
     ......
}

我不知道它崩溃的原因。每次发布通知时都不会崩溃(似乎是随机的)。

编辑: 只有一个对象可以注册接收通知。 init方法和调用的选择器如下所示。我认为没有什么可以导致崩溃。 _label和_joinGame都是SKLabelNodes

-(id)init
{ ...
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(addGameCenterOption) name:AUTHENTICATED_NOTIFICATION object:nil];
...
}

-(void)addGameCenterOption
{
    _label.text = @"";
    _joinGame.text = @"Start multiplayer game";
    _signedIn = YES;
}
编辑:我已经更改了应用程序,因此没有注册任何对象来观察通知,但它仍然会崩溃(随机)。

3 个答案:

答案 0 :(得分:1)

由于您正在修改UI元素,因此请在addGameCenterOption的开头添加一个断言,以确保您位于主线程上。此外,在与元素交互之前做一些间接的事情,比如在设置任何属性之前记录它们的类以验证它们是否仍然存在。

如果设置了例外断点(左侧窗格),Xcode应显示导致崩溃的确切行。

答案 1 :(得分:1)

这很可能是由已注册的观察者引起的,该观察者在发送通知时已被释放,但观察者未注销。

确保添加观察者的所有类:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addGameCenterOption) name:AUTHENTICATED_NOTIFICATION object:nil];

在释放观察者之前也要删除它:

[[NSNotificationCenter defaultCenter] removeObserver:self AUTHENTICATED_NOTIFICATION object:nil];

答案 2 :(得分:0)

对我来说,这是因为选择器的功能签名不正确。我指定了没有参数的选择器:#selector(MyClass.myFunc)

但方法定义如下:

class MyClass {
    ...

    @objc func myFunc(completion: (() -> ())?)
        // function body
    }
}

意识到选择器不允许使用此签名后,我像这样更新了代码。

class MyClass {
    ...

    @objc func functionForMySelector() {
        myFunc(completion: nil)
    }

    func myFunc(completion: (() -> ())?)
        // function body
    }
}

并这样定义我的选择器:#selector(MyClass.functionForMySelector)