Что происходит при наблюдении UIApplicationDidEnterBackgroundNotification на старой iOS без многозадачности?
У меня есть эта строка кода:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
Прекрасно работает в симуляторе iPhone 4.3 и на моем iPhone под управлением 4.x. Однако происходит сбой на iPhone под управлением 3.x. Имеет смысл. Я предполагаю, что эта строка кода не работает, когда нет многозадачности.
Мне сложно отлаживать, потому что человек, который тестирует меня с системой 3.x, находится в удаленном месте. Я даже не уверен, оценивает ли символ UIApplicationDidEnterBackgroundNotification правильную строку, или ноль, или случайную неинициализированную память, или что в этой ОС.
Но кроме того, чтобы выяснить, почему это терпит неудачу, что я могу сделать с некоторым усилием, что я должен делать? Как определить, существует ли конкретное уведомление, прежде чем я его увижу? Или я проверяю, доступна ли многозадачность как общая категория? Я думаю, я думал, что строка кода будет в безопасности. Если ОС никогда не генерирует это уведомление, я не получаю уведомление, но линия не должна падать.
4 ответа
Вы должны проверить, является ли версия 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.
Просто для вашего понимания, проблема возникает не столько при регистрации неизвестного уведомления, сколько в том, что имя уведомления не существует (как вы подозревали), и на самом деле дело даже не в том, что UIApplicationDidEnterBackgroundNotification
является NULL
, но по факту &UIApplicationDidEnterBackgroundNotification
является NULL
; это то, как вы проверяете это, на самом деле.
Итак, что происходит (случилось) в вашем случае, это просто NULL разыменование, NSNotificationCenter
даже не вмешивался.
Я думаю, что это будет работать для вас, я не проверял.
#ifdef _USE_OS_4_OR_LATER
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationDidEnterBackgroundNotification object:nil];
#endif
Фоновая обработка (т.е. многозадачность) не существовала до 4.0. Регистрация в несуществующем уведомлении не должна причинять много вреда. Я ожидал бы, что это просто никогда не будет вызвано. Но я признаю, что я не проверял это с уведомлениями.
Приведенный ниже пример проверяет во время выполнения версию os (здесь 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];