Luuching App com URL (via o handleopenurl da UIApplicationDelegate) trabalhando com o iOS 4, mas não no iOS 3.2
-
26-09-2019 - |
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.
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 eapplication:handleOpenURL:
é chamado se eapplication:didFinishLaunchingWithOptions:
retornou sim. - Se o aplicativo estiver se tornando ativo do estado suspenso, então
application:didFinishLaunchingWithOptions:
não é chamado, masapplication: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 issoapplication: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:
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.