简体   繁体   English

NSNotificationCenter代码可在iPhone中使用,但不能在iPad上使用

[英]NSNotificationCenter Code works in iPhone but not on iPad

[[NSNotificationCenter defaultCenter] addObserver:self 
                                      selector:@selector(didEnterBackground:)
                                      name:UIApplicationDidEnterBackgroundNotification
                                      object:nil];

Why does this code work on iPhone simulator but not on iPad simulator? 为什么此代码在iPhone模拟器上却不能在iPad模拟器上起作用? I get EXC_BAD_ACCESS on this code. 我在此代码上得到EXC_BAD_ACCESS Tried version iOS 3.2, 4.2, 4.3. 尝试过iOS 3.2、4.2、4.3版本。

To expand on Chiefly Izzy's comment, UIApplicationDidEnterBackgroundNotification is defined as an extern NSString * . 为了扩大对Chiefly Izzy的评论, UIApplicationDidEnterBackgroundNotification被定义为extern NSString * It's often preferable to define constant strings that way, rather than as: 通常最好这样定义常量字符串,而不是这样:

#define UIApplicationDidEnterBackgroundNotification @"whatever"

Because it allows you to test by identity rather than equality, because all attempts by the user to refer to UIApplicationDidEnterBackgroundNotification will refer to the same instance of it, not just to (possibly, subject to compiler fiat) separate NSStrings with the same value. 因为它允许您通过身份而不是相等性进行测试,所以用户尝试引用UIApplicationDidEnterBackgroundNotification的所有尝试都将引用它的相同实例,而不仅仅是(可能受编译器命令的约束)具有相同值的单独NSString。

The actual value for UIApplicationDidEnterBackgroundNotification is contained within UIKit, so when the UIKit library is loaded the pointer will be filled in. The problem is that iOS 3.2 doesn't define UIApplicationDidEnterBackgroundNotification, so what you end up with is an undefined pointer. UIApplicationDidEnterBackgroundNotification的实际值包含在UIKit中,因此,在加载UIKit库时,将填充指针。问题是iOS 3.2没有定义UIApplicationDidEnterBackgroundNotification,因此最终得到的是未定义的指针。 Hence you pass an undefined pointer to the NSNotificationCenter, causing the crash when it attempts to read it. 因此,您将未定义的指针传递给NSNotificationCenter,从而在尝试读取它时导致崩溃。

The smart thing to do is probably: 聪明的事情可能是:

UIDevice *currentDevice = [UIDevice currentDevice];

if( [currentDevice respondsToSelector:@selector(isMultitaskingSupported)] && 
    [currentDevice isMultitaskingSupported])
{
    [[NSNotificationCenter defaultCenter] addObserver:self 
                              selector:@selector(didEnterBackground:)
                              name:UIApplicationDidEnterBackgroundNotification
                              object:nil];
}

So you check whether the version of the UIDevice class on this device knows that multitasking is even a possibility and if so whether multitasking is supported. 因此,您检查该设备上的UIDevice类的版本是否知道甚至可以执行多任务,如果可以,则是否支持多任务。 The standard C shortcut evaluation means the thing after the && will be evaluated only if the thing before it succeeds, so there's no chance of accidentally issuing an unrecognised method call. 标准的C快捷方式评估意味着&&之后的事物只有在成功之前的事物中才会被评估,因此不会偶然发出无法识别的方法调用。

Only if multitasking is supported do you register for the notification. 仅当支持多任务处理时,您才注册该通知。 This will be safe because the UIApplicationDidEnterBackgroundNotification string was introduced at the same time as multitasking. 这是安全的,因为在多任务处理的同时引入了UIApplicationDidEnterBackgroundNotification字符串。 There is no device that supports multitasking and doesn't provide the string. 没有支持多任务并且不提供字符串的设备。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM