Luuching App com URL (via o handleopenurl da UIApplicationDelegate) trabalhando com o iOS 4, mas não no iOS 3.2

StackOverflow https://stackoverflow.com/questions/3612460

Pergunta

Eu implementei uiapplicationDelegate's

application:didFinishLaunchingWithOptions:

e

application:handleOpenURL:

De acordo com a especificação, ou seja,

application:didFinishLaunchingWithOptions:
returns YES 

e

application:handleOpenURL: opens the URL. 

O código funciona no iOS 4 (em ambos os casos, ou seja, quando o aplicativo é iniciado e quando se torna ativo do estado suspenso). No entanto, o código não funciona no iOS 3.2.

Foi útil?

Solução

Eu dou uma resposta à minha própria pergunta. Descobrir a solução demorou um pouco e foi bastante frustrante. Se você fizer uma pesquisa na Internet, encontrará algumas respostas parciais, mas ainda demorei um pouco para descobrir a solução a seguir e espero que acrescente alguma clareza.

Então, primeiro, o comportamento recomendado do seu aplicativo parece ser o seguinte (ver Abertura dos tipos de arquivos suportados em iOS ref Lib):

  • Não implemente applicationDidFinishLaunching: (Veja a nota em UiapplicationDelegate).
  • Implemento application:didFinishLaunchingWithOptions: E verifique o URL, retorne sim se você puder abri -lo, caso contrário, não, mas não o abra.
  • Implemento application:handleOpenURL: e abra o URL, retorne sim se for bem -sucedido, caso contrário, não.

No iOS 4, passar um URL para um aplicativo resulta em um dos dois comportamentos a seguir:

  • Se o aplicativo for lançado, então application:didFinishLaunchingWithOptions: é chamado e application:handleOpenURL: é chamado se e application:didFinishLaunchingWithOptions: retornou sim.
  • Se o aplicativo estiver se tornando ativo do estado suspenso, então application:didFinishLaunchingWithOptions: não é chamado, mas application:handleOpenURL: é chamado.

No entanto, no iOS 3.2, parece que application:handleOpenURL: nunca é chamado! Uma dica de que o comportamento é diferente no iOS 3.2 pode ser encontrado em Manuseando solicitações de URL. Lá você encontra isso application:handleOpenURL: é chamado se application:didFinishLaunchingWithOptions: não é implementado, mas applicationDidFinishLaunching: é implementado. Mas application:handleOpenURL: não é chamado se application:didFinishLaunchingWithOptions: é implementado.

Portanto, uma solução para fazer o código funcionar em 3.2 e 4.0 é:

  • Abra o URL em application:didFinishLaunchingWithOptions:, mas depois retorne não para evitar isso application:handleOpenURL: é chamado.
  • Abra o URL em application:handleOpenURL:, caso você esteja abaixo de 4.0 e o aplicativo estivesse em estado suspenso.

Encontrei esta solução em outro post, mas fiquei confuso, porque contradiz a recomendação na documentação da Ref Lib (a saber, que devemos retornar sim em application:didFinishLaunchingWithOptions:). (Naquele momento, eu não percebi que a documentação o contradiz).

Acredito que o comportamento atual do iOS 4.0 será o comportamento futuro, prefiro a seguinte solução:

  • Não implemente applicationDidFinishLaunching:.
  • Implemento application:didFinishLaunchingWithOptions: E verifique o URL, retorne sim se você puder abri -lo, caso contrário, não, mas não o abra. Se estivermos no 3.2, abra o URL.
  • Implemento application:handleOpenURL: e abra o URL, retorne sim se for bem -sucedido, caso contrário, não.

Então, em resumo, implemento o comportamento do iOS 4 e adicionei a seguinte linha a application:didFinishLaunchingWithOptions:

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

que fazem o código funcionar em 3.2.

Outras dicas

application:handleOpenURL: agora está depreciado.

A partir do iOS 4.2, você pode usar isso para abrir URLs:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 
        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

Documentação:

https://developer.apple.com/library/ios/#documentation/uikit/reference/uiapplicationDelegate_protocol/reference/reference.html

Comecei a escrever um aplicativo que usava a API do Dropbox. Para entender o conceito, executei um aplicativo de amostra usando minha chave/secreto mencionado no Dropbox/Developer documentação. Depois que o aplicativo de amostra começou a funcionar, usei os mesmos valores de chave/secreto para minha aplicação.

Para um aplicativo de amostra, a implementação do HandleOpenurl (ou OpenUrl no iOS 4.2) é executada conforme o esperado. Por algum motivo estranho, não foi o caso do meu aplicativo. Meu aplicativo entrou em segundo plano para mostrar a tela de login e a página de autenticação do Dropbox. Após o login e a autenticação bem -sucedidos, meu aplicativo nunca entrou em primeiro plano. Era verdade para o simulador de plataforma e o dispositivo (iPad)

Eu tentei quase tudo listado na internet, incluindo este post. Obrigado. Não houve sucesso, no entanto.

Finalmente INICIADO Trabalhando para minha inscrição quando fiz a seguinte:

  • No simulador, selecione "IOS Simulator -> Redefinir conteúdo e configurações" e redefinir.
  • No dispositivo, excluí o executável relacionado ao aplicativo de amostra e que, por sua vez, exclua o cache associado a ele.

Adicione o seguinte ao 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;
}

onde o MVC é meu principal viewcontroller e NC meu controlador de navegação.

Então, no MainViewController, faça algo assim:

- (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];
    ...
}

Depois de declarar o handleopenurl no .h, é claro.

Obrigado a Christian por se esforçar para isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top