注册远程通知时iOS7崩溃

问题描述 投票:3回答:2

这在iOS8中运行良好,但是当我把它放在iOS7设备上时,它会崩溃,从而导致错误

-[UIApplication registerUserNotificationSettings:]: unrecognized selector sent to instance 0x14e56e20

我在AppDelegate注册通知:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

#ifdef __IPHONE_8_0
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
                                                                                         |UIRemoteNotificationTypeSound
                                                                                         |UIRemoteNotificationTypeAlert) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
    //register to receive notifications
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif

    application.applicationIconBadgeNumber = 0;

    return YES;
}

当我设置断点时,它总是运行__IPHONE_8_0块中的代码。我怎么能检测到哪个块运行?

ios objective-c
2个回答
5
投票

你不应该像这样使用预处理器。更好的方法是检查您的对象是否响应您发送的消息,而不是检查操作系统版本。将您的方法更改为

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
    {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
                                                                                             |UIRemoteNotificationTypeSound
                                                                                             |UIRemoteNotificationTypeAlert) categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    else
    {
        //register to receive notifications
        UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
        [application registerForRemoteNotificationTypes:myTypes];
    }
    application.applicationIconBadgeNumber = 0;

    return YES;
}

这里有几点需要注意。我将[UIApplication sharedApplication]更改为application,因为委托已经在你的UIApplication实例中传递,所以只需直接访问它。

respondsToSelector:是来自NSObject的一种方法,它将告诉你接收器application是否会响应选择器(或方法)。你只需要像@selector(myMethod:)一样包装方法来检查它。在使用较新的API时,这是一种很好的做法,可以实现向后兼容性。在处理id类型的匿名对象时,您还希望进行此类检查。

至于为什么#ifdef __IPHONE_8_0不起作用,请看看这个答案:https://stackoverflow.com/a/25301879/544094


2
投票

#ifdef __IPHONE_8_0是一个编译时指令。因为您的编译目标通常是最新的iOS版本,所以这将始终是编译到您的应用程序中的代码。这与应用程序运行的设备无关,因为它是在应用程序存在之前完成的(因此肯定在应用程序运行之前)。

相反,您应该使用运行时检查。您可以检查iOS版本,或者您可以检查是否存在您尝试使用的方法:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings)]) {
  // Do iOS8+ stuff.
} else {
  // Do iOS7- stuff.
}
© www.soinside.com 2019 - 2024. All rights reserved.