2010-08-31 14 views
11

He implementado de UIApplicationDelegatelauching App con URL (a través de handleOpenURL de UIApplicationDelegate) que trabaja bajo iOS 4, pero no bajo iOS 3.2

application:didFinishLaunchingWithOptions: 

y

application:handleOpenURL: 

acuerdo con la especificación, es decir,

application:didFinishLaunchingWithOptions: 
returns YES 

y

application:handleOpenURL: opens the URL. 

El código funciona en iOS 4 (en ambos casos, es decir, cuando se inicia la aplicación y cuando se activa desde el estado suspendido). Sin embargo, el código no funciona en iOS 3.2.

+0

¿Cuál es el problema en 3.2? ¿Error de mensajes? ¿Las líneas de código se rompen? –

+0

Parece que el delegado no recibe el mensaje handleOpenURL en absoluto si respondió el mensaje didFinishLaunchingWithOptions, incluso si ese método devolvió SÍ. La documentación de la API me sugirió un comportamiento diferente. –

Respuesta

33

Respondo a mi pregunta. Descubrir la solución me llevó un tiempo y fue bastante frustrante. Si haces una búsqueda en Internet, encuentras algunas respuestas parciales, pero todavía me tomó un tiempo encontrar la siguiente solución y espero que añada algo de claridad.

Así que, primero, el comportamiento recomendado de su aplicación parece ser el siguiente (ver Opening Supported File Types en IOS Ref Lib):

  • no implementan applicationDidFinishLaunching: (véase la nota al UIApplicationDelegate).
  • Implemente application:didFinishLaunchingWithOptions: y revise la URL, devuelva SÍ si puede abrirla, de lo contrario NO, pero no la abra.
  • Implemente application:handleOpenURL: y abra la URL, devuelva SÍ si tiene éxito, de lo contrario NO.

En IOS 4, el paso de una dirección URL a un resultado de la aplicación de uno de los dos comportamientos siguientes:

  • Si la aplicación se inicia a continuación application:didFinishLaunchingWithOptions: se llama y application:handleOpenURL: se llama si y application:didFinishLaunchingWithOptions: regresaron SÍ.
  • Si la aplicación se está activando desde el estado suspendido, entonces no se llama a application:didFinishLaunchingWithOptions: pero se llama a application:handleOpenURL:.

Sin embargo, en iOS 3.2 parece que nunca se llama a application:handleOpenURL:! Una sugerencia de que el comportamiento es diferente en iOS 3.2 se puede encontrar en Handling URL Requests. Ahí encuentra que se llama application:handleOpenURL: si application:didFinishLaunchingWithOptions: no está implementado, pero se implementa applicationDidFinishLaunching:. Pero application:handleOpenURL: no se llama si se implementa application:didFinishLaunchingWithOptions:.

Por lo tanto, una solución para hacer que el código bajo 3.2 y 4.0 es:

  • abrir la URL application:didFinishLaunchingWithOptions:, pero luego no retorno para evitar que application:handleOpenURL: se llama.
  • Abra la URL en application:handleOpenURL:, en caso de que tenga menos de 4.0 y la aplicación estuviera en estado suspendido.

He encontrado esta solución en otro post, pero yo estaba confundido, ya que contradice la recomendación en la documentación IOS Ref Lib (es decir, que debemos volver SI en application:didFinishLaunchingWithOptions:). (En ese momento no me di cuenta de que la documentación se contradice).

creo que el comportamiento actual de iOS 4.0 será el comportamiento futuro prefiero la siguiente solución:

  • no implementan applicationDidFinishLaunching:.
  • Implemente application:didFinishLaunchingWithOptions: y revise la URL, devuelva SÍ si puede abrirla, de lo contrario NO, pero no la abra. Si estamos en 3.2, abre la URL.
  • Implemente application:handleOpenURL: y abra la URL, devuelva SÍ si tiene éxito, de lo contrario NO.

Así que en resumen, puedo implementar el comportamiento IOS 4, y añadió la siguiente línea a application:didFinishLaunchingWithOptions:

 
    if([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3.2"]) { 
     [self application:application handleOpenURL:url]; 
    } 

que hacen que el código funcione en el punto 3.2.

+0

Gracias, tuve el mismo problema y esta respuesta me ahorró mucho tiempo. – bosmacs

+0

Todavía no pude hacer que esto funcionara hasta que me di cuenta de que tenía mi proyecto compilando con un SDK base de 3.2 pero ejecutándose en un simulador 4.0. ¿El resultado? Cuando se activa, NINGUNO de los métodos anteriores son llamados. Una vez que cambié el SDK base a 4.0, todo funcionó. No estoy seguro de cómo hacerlo funcionar en 3.2 ipad aunque. –

+0

Buen punto. Además: Simulator no fue un entorno de prueba muy confiable para mí. Encontré cosas para trabajar en un simulador que no funcionaba en un dispositivo y viceversa. Un ejemplo: http://stackoverflow.com/questions/3616981 - pero el simulador ha mejorado ahora. –

2

Empecé a escribir la aplicación que utilizaba Dropbox api. Para entender el concepto, ejecuté una aplicación de muestra usando mi clave/secreto mencionado en dropbox/developer documentation. Una vez que la aplicación de muestra comenzó a funcionar, utilicé la misma clave/valores secretos para mi aplicación.

Para la aplicación de ejemplo, la implementación de handleOpenURL (o openURL en iOS 4.2) se ejecuta como se esperaba. Por alguna extraña razón, no fue el caso para mi aplicación. Mi aplicación entró en segundo plano para mostrar la pantalla de inicio de sesión y la página de autenticación de Dropbox. Después del inicio de sesión y la autenticación exitosos, mi aplicación nunca entró en primer plano. Fue cierto tanto para la plataforma Simulador como para el dispositivo (iPad)

Intenté casi todo lo que aparece en Internet, incluida esta publicación. Gracias. Sin embargo, NO hubo ningún éxito.

Por último, se EMPEZAR trabajando para mi aplicación cuando lo hice siguiente:

  • en el simulador, seleccione "simulador de iOS -> Restablecer contenidos y ajustes", y RESET.
  • En el dispositivo, eliminé el ejecutable relacionado con la aplicación de muestra y que a su vez borré el caché asociado.
0

Agregue lo siguiente al final de application:DidFinishLaunchingWithOptions:

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

    ...  

    NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey]; 
    if (url != nil && [url isFileURL]) { 
     return YES; 
    } else return NO; 
} // End of application:didFinishLaunchingWithOptions: 

// New method starts 
-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 
{ 
    mvc = [nc.viewControllers objectAtIndex:0]; 
    if (url != nil && [url isFileURL]) { 
     [mvc handleOpenURL:url]; 
    } 
    return YES; 
} 

donde MVC es mi principal ViewController y nc mi controlador de navegación.

Luego, en el MainViewController, hacer algo como esto:

- (void)handleOpenURL:(NSURL *)url { 
    [self.navigationController popToRootViewControllerAnimated:YES]; 

    // Next bit not relevant just left in as part of the example 
    NSData *jsonData = [NSData dataWithContentsOfURL:url];   
    NSError *error; 
    NSDictionary *dictionary = [[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error] objectAtIndex:0]; 
    [self managedObjectFromStructure:dictionary withManagedObjectContext:self.context]; 
    ... 
} 

después de declarar handleOpenURL en el .h por supuesto.

Gracias a Christian por esforzarse en esto.

Cuestiones relacionadas