Tengo una aplicación que usa notificaciones locales. En iOS 7 todo funciona bien, pero en iOS 8, la aplicación tiene que pedir el permiso del usuario para mostrar las notificaciones. Para pedir permiso en iOS 8 que estoy usando:

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

{
  [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}

Funciona bien en Xcode 6 y iOS 8. Cuando abro el mismo proyecto en Xcode 5, el error es una Cuestión Semántica. «El uso de identificador no declarado ‘UIUserNotificationSettings’.»

¿Cómo puedo obtener la aplicación para que funcione con iOS 7 & 8, y tener las notificaciones funcionan correctamente en ambas versiones.

  • Leer el «SDK Guía de Compatibilidad» en la documentación.
  • ¿Usted realmente necesita para trabajar con las dos versiones de Xcode? Sólo el uso de Xcode 6 y puede apoyar tanto a las versiones de iOS.
  • Revise este enlace iOS 8 ha cambiado el registro de notificación de stackoverflow.com/a/24773465/3560390
  • Usted necesidad de aclarar un par de cosas para obtener la respuesta adecuada (por el momento ambos están equivocados). ¿Cuál es su objetivo? ¿Quieres un Destino para la Implementación de iOS 7 o versiones anteriores, Y ser capaz de tener una Base SDK de iOS 7 cuando el uso de Xcode 5 y una Base SDK de iOS 8 cuando el uso de Xcode 6?
  • El proyecto de implementación de destino es la 7.0. Mientras que se podría compilar en Xcode 6 por su parte, la aplicación se bloqueará en la puesta en marcha de un dispositivo de iOS 7.
  • A continuación, vea mi respuesta. Es compatible tanto con iOS 7 y 8, así como trabajando en Xcode 5 y 6. La respuesta que aceptan no funciona incluso en iOS 8.

InformationsquelleAutor dannysandler | 2014-07-25

6 Comentarios

  1. 62

    La siguiente respuesta hace un par de hipótesis:

    1. La aplicación debe construir adecuadamente con una Base SDK de iOS 8 cuando el uso de Xcode 6, y se debe construir adecuadamente con una Base SDK de iOS 7 al usar Xcode 5.
    2. La aplicación debe soportar un Destino para la Implementación de iOS 7 (o anterior), independientemente de la Base y SDK versión de Xcode.

    Código:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        //None of the code should even be compiled unless the Base SDK is iOS 8.0 or later
    #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
        //The following line must only run under iOS 8. This runtime check prevents
        //it from running if it doesn't exist (such as running under iOS 7 or earlier).
        if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
            [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
        }
    #endif
    }

    Todo esto está cubierto en la Apple El SDK de la Guía de Compatibilidad de.

    • Esta es elegante y correcto. He encontrado varios errores en mi respuesta y no existe una forma sencilla de arreglar ,así que lo borré.
    • Usted no puede revelar su aplicación basada en esta solución antes de que Apple versión de XCode 6.
    • Pero la respuesta fue preguntado durante la beta. La respuesta es correcta y es lo que el OP sea necesario (o no han aceptado). Downvoting la respuesta, ya que Apple aún no se (pero probablemente hoy) comenzó a aceptar aplicaciones de Xcode 6 es inapropiado.
    • La respuesta también puede ser adaptado fácilmente para cualquier persona que necesita el apoyo de iOS 7 y iOS 6, por ejemplo. O en el plazo de dos años para cualquier persona que necesite apoyo iOS 9 y iOS 7.
  2. 11

    He implementado simplemente –

    if([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
    
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    
    } else {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge];
    }
  3. 3

    Hasta ahora, este fragmento de código que funciona para mí, y su simple reutilización:

    //-- Set Notification
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
    {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
    }
    • Esto no va a funcionar (no compila) cuando construida con Xcode 5 y una Base SDK de iOS 7. Ese fue el punto central de la cuestión. El código que se necesita para construir y ejecutar si el uso de Xcode 5 o Xcode 6.
    • Su pregunta requiere el código de trabajo para ios7 y ios8. Si quieres compilar para ios8 debe utilizar xcode 6.
    • No es mi pregunta, pero leerlo de nuevo. El OP quiere construir la aplicación, tanto con Xcode 5 (Base SDK de iOS 7) y Xcode 6 (Base SDK de iOS 8). Su respuesta no trabajo con Xcode 5 (Base SDK de iOS 7).
    • «¿Cómo puedo obtener la aplicación para que funcione con iOS 7 & 8, y tener las notificaciones funcionan correctamente en ambas versiones.» No, esta solución no funciona para Xcode 5, pero si el uso de xcode 5, usted no será capaz de compilar para ios8. Usted no puede tener las dos formas.
  4. 3

    En caso de que desea compilar contra mayores Sdk o tienen una razón especial para hacerlo, usted puede tratar de llamar a todo el asunto de forma dinámica:

    #ifdef __IPHONE_8_0
    #define USING_IOS8_SDK
    #else //iOS <8 SDK compatibility definitions
    #define UIUserNotificationTypeNone    (0)
    #define UIUserNotificationTypeBadge   (1 << 0)
    #define UIUserNotificationTypeSound   (1 << 1)
    #define UIUserNotificationTypeAlert   (1 << 2)
    #endif
    ...
    if ([_sharedApplication respondsToSelector:NSSelectorFromString(@"registerUserNotificationSettings:")])
    {
    NSUInteger settingsParam = (UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound);
    id categoriesParam = nil;
    #ifdef USING_IOS8_SDK
    //Perform direct call when using iOS 8 SDK
    [_sharedApplication registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:settingsParam categories:categoriesParam]];
    #else
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    //Do the dynamic stuff
    //Get UIUserNotificationSettings class reference
    Class settings = NSClassFromString(@"UIUserNotificationSettings");
    if (settings) {
    //Prepare class selector
    SEL sel = NSSelectorFromString(@"settingsForTypes:categories:");
    //Obtain a method signature of selector on UIUserNotificationSettings class
    NSMethodSignature *signature = [settings methodSignatureForSelector:sel];
    //Create an invocation on a signature -- must be used because of primitive (enum) arguments on selector
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.selector = sel;
    invocation.target = settings;
    //Set arguments
    [invocation setArgument:&settingsParam atIndex:2];
    [invocation setArgument:&categoriesParam atIndex:3];
    //Obtain an instance by firing an invocation
    NSObject *settingsInstance;
    [invocation invoke];
    [invocation getReturnValue:&settingsInstance];
    //Retain an instance so it can live after quitting method and prevent crash :-)
    CFRetain((__bridge CFTypeRef)(settingsInstance));
    //Finally call the desired method with proper settings
    if (settingsInstance)
    [_sharedApplication performSelector:NSSelectorFromString(@"registerUserNotificationSettings:") withObject:settingsInstance];
    }
    #pragma clang diagnostic pop
    #endif
    }

    Esta perfectamente debe compilar en iOS 7 SDK y el trabajo (eficacia), en iOS 8 dispositivos, ignorado en las más antiguas.

    Migrar el proyecto a iOS 8 SDK es otra solución, pensó, pero todavía hay opciones.

    • Gracias eso fue realmente útil
  5. 0
    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
    [application registerUserNotificationSettings:settings];
    }
  6. -2

    Usted puede intentar algo como esto:

    if (NSClassFromString(@"UIUserNotificationSettings") != nil) {
    //your iOS 8 code here
    #define isiOS8
    }
    else {
    #undef isiOS8
    }
    #ifdef isiOS8
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    #endif

    Es un poco más complicado pero funciona bien.

    ** EDIT ** código Fijo mejor

    • Ninguno de esos trabajado en Xcode 5, pero ambos trabajaron en Xcode 6.
    • Me sigue apareciendo el Error Semántico. imagen (no sé cómo cargar imágenes en los comentarios)
    • Ah! Veo lo que quieres decir. Déjame que piense.
    • muchas gracias. este compilado en Xcode 5 & 6.
    • ¿Cómo funciona esto? el if (NSClassFromString( parte es una instrucción tiempo de ejecución (se evalúa en tiempo de ejecución), pero la #ifdef isiOS8 es una directiva de preprocesador (se evalúa en tiempo de compilación).
    • Este código no funciona en absoluto. Puede compilar pero bajo iOS 8 no registrar nada debido a que el código no será compilado en.
    • Este no puede trabajar, porque definir # / #undef son evaluadas por el pre-procesador. El preprocesador ve #define seguido por #undef, así isiOS8 será indefinido y registerUserNotificationSettings no se llama.

Dejar respuesta

Please enter your comment!
Please enter your name here