在没有多任务处理的旧 iOS 上观察 UIApplication DidEnterBackgroundNotification 时会发生啥?

Posted

技术标签:

【中文标题】在没有多任务处理的旧 iOS 上观察 UIApplication DidEnterBackgroundNotification 时会发生啥?【英文标题】:What happens when observing UIApplicationDidEnterBackgroundNotification on old iOS without multitasking?在没有多任务处理的旧 iOS 上观察 UIApplication DidEnterBackgroundNotification 时会发生什么? 【发布时间】:2011-09-13 04:09:53 【问题描述】:

我有这行代码:

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

在 iPhone 4.3 模拟器和运行 4.x 的 iPhone 上运行良好。但是,在运行 3.x 的 iPhone 上会发生崩溃。说得通。我的猜测是,当没有多任务处理时,那行代码不起作用。

我很难调试,因为使用 3.x 系统为我测试的人在远程位置。我什至不确定符号 UIApplicationDidEnterBackgroundNotification 是否计算为正确的字符串、nil 或随机未初始化内存,或者该操作系统上的什么。

但是除了找出失败的原因之外,我可以通过一些努力来做到这一点,我应该怎么做?如何在观察之前检测特定通知是否存在?或者我是否检查多任务处理是否可以作为一般类别使用?我想我认为这行代码是安全的。如果操作系统从不生成该通知,那么我不会收到通知,但线路不应该崩溃。

【问题讨论】:

【参考方案1】:

您应该在编译时检查 ios 版本是否为 4.0 或更高版本(为此有内置的预处理器#defines)并测试多任务支持(以防它在设备上被禁用而原本支持):

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
    if([[UIDevice currentDevice]
        respondsToSelector:@selector(isMultitaskingSupported)] &&
       [[UIDevice currentDevice] isMultitaskingSupported])
    
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
    
#endif

您不必使用#if,但它可以节省编译额外检查,您知道这些检查将始终返回 false。

【讨论】:

好的,好的答案,已接受。我更喜欢检查功能而不是版本。我更愿意检查具体的电话,所以如果有人知道他们是否像[[NSNotificationCenter defaultCenter] canSendNotification:UIApplicationDidEnterBackgroundNotification],请告诉我。【参考方案2】:

只是为了您的启发,问题发生在注册未知通知时并没有发生,而是通知名称不存在(正如您所怀疑的那样),实际上甚至不是UIApplicationDidEnterBackgroundNotificationNULL,但实际上&UIApplicationDidEnterBackgroundNotification就是NULL;那是how you test for it,事实上。

所以在你的情况下发生(发生)的是一个简单的 NULL 取消引用,NSNotificationCenter 甚至没有参与。

【讨论】:

【参考方案3】:

我认为这对你有用,我没有检查。

#ifdef _USE_OS_4_OR_LATER
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
#endif

【讨论】:

不,我不这么认为。这将有条件地包含在构建中。我想制作一个在 iOS 3.x 和 iOS 4.x 上运行的版本。我想检测我在运行时应该做什么。【参考方案4】:

4.0 之前不存在背景(即多任务处理)。注册到一个不存在的通知应该不会造成太大的损害。我希望它永远不会被调用。但我承认我没有用通知测试过。

以下示例在运行时检查操作系统版本(此处为 4.0 和 3.2),然后执行一种或另一种方法。

NSString *requiredSystemVersion = @"4.0"; 
NSString *currentSystemVersion = [[UIDevice currentDevice] systemVersion];
if (![currentSystemVersion compare:requiredSystemVersion options:NSNumericSearch] != NSOrderedAscending) [self do4dotXStuff];

requiredSysVer = @"3.2";
if ([currentSystemVersion compare:requiredSystemVersion options:NSNumericSearch] != NSOrderedAscending) [self do3dotTwoStuff];

【讨论】:

以上是关于在没有多任务处理的旧 iOS 上观察 UIApplication DidEnterBackgroundNotification 时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

应用程序在后台时未触发 iOS 本地通知

如何在未处理的任务异常上崩溃?

是否可以在 iOS 9 上让您的 iPad 应用退出多任务处理?

iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

使用多处理池在 python 中加速 TFLite 推理

iOS 多任务处理:系统在进入后台时执行的减少