“O aplicativo tentou apresentar modalmente um controlador ativo”?

100

Acabei de encontrar um travamento mostrando um NSInvalidArgumentExceptioncom esta mensagem em um aplicativo que não estava fazendo isso antes.

O aplicativo tentou apresentar modalmente um controlador ativo UITabBarController: 0x83d7f00.

Eu tenho um UITabBarControllerque eu crio no AppDelegatee dou a ele o array de UIViewControllers.

Desejo apresentar um deles de forma modal ao tocar nele. Eu fiz isso implementando o método delegado

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController

Se esse controlador de visualização for da classe que desejo apresentar modalmente, retorno NÃO e faço

[tabBarController presentModalViewController:viewController animated:YES];

E agora estou recebendo aquele erro, o que parece significar que você não pode apresentar modalmente um controlador de visualização que esteja ativo em outro lugar (na barra de guias ...). Devo dizer que estou no XCode 4.2 Developer Preview 7, então este é o iOS 5 (eu sei sobre o NDA, mas acho que não estou dando detalhes proibidos). Atualmente, não tenho uma instalação do XCode para testar se a compilação do iOS4 SDK trava, mas tenho quase certeza de que não.

Eu só queria perguntar se alguém passou por esse problema ou tem alguma sugestão

Javier Soto
fonte
Antes do iOS 5, isso não gerava uma exceção, mas não retornava nada. Do iOS 5 em diante, esse comando levanta uma exceção.
Frédéric Adda

Respostas:

103

Suponha que você tenha três controladores de visualização instanciados assim:

UIViewController* vc1 = [[UIViewController alloc] init];
UIViewController* vc2 = [[UIViewController alloc] init];
UIViewController* vc3 = [[UIViewController alloc] init];

Você os adicionou a uma barra de guias como esta:

UITabBarController* tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:vc1, vc2, vc3, nil]];

Agora você está tentando fazer algo assim:

[tabBarController presentModalViewController:vc3];

Isso gerará um erro porque o Tab Bar Controller tem um controle mortal sobre o controlador de visualização que você forneceu. Você não pode adicioná-lo ao conjunto de controladores de visualização na barra de guias ou não pode apresentá-lo modalmente.

A Apple espera que você trate seus elementos de interface do usuário de uma determinada maneira. Isso provavelmente está enterrado nas Diretrizes de Interface Humana em algum lugar como um "não faça isso porque não esperamos que você queira fazer isso".

lswank
fonte
6
A questão é que isso não era absolutamente nenhum problema antes do iOS 5, daí minha preocupação! O que fiz foi adicionar um UIViewController fictício à barra de guias e apresentar modalmente a instância real da subclasse do controlador de visualização.
Javier Soto,
1
@Iswank, agora no iOS 6, para tornar as coisas "mais fáceis", eles descontinuaram o presentModalViewController causando todos os tipos de problemas de rotação ... você precisa usar o presentViewController: animado: conclusão e verificar como seu aplicativo está lidando com as mudanças
whyoz
15

Eu tenho o mesmo problema. Tento apresentar o controlador de exibição logo após dispensar.

[self dismissModalViewControllerAnimated:YES];

Quando tento fazer sem animação, funciona perfeitamente, então o problema é que o controlador ainda está vivo. Eu acho que a melhor solução é usar dismissViewControllerAnimated:completion:para iOS5

Danil
fonte
Ele falha se você dispensá-lo animado porque, no momento em que deseja apresentar o controlador de visualização modal novamente, ele ainda está modalmente na tela, sendo animado.
Pascal
2
É obsoleto no IOS 6.0
Sumit Kumar Saha
12

No meu caso, eu estava tentando apresentar o viewController (tenho a referência do viewController no TabBarViewController) de diferentes controladores de visualização e estava travando com a mensagem acima. Nesse caso, para evitar a apresentação, você pode usar

viewController.isBeingPresented

!viewController.isBeingPresented {
          // Present your ViewController only if its not present to the user currently.
}

Pode ajudar alguém.

Karthick Ramesh
fonte
ele está funcionando apenas em viewWillappperar, mas quando eu verifiquei antes de apresentar o viewController que já está apresentado, é sempre return false.
guru de
1
Não está funcionando para mim. Ainda consegue travar o aplicativo. (! viewController.presentingViewController) resolveu o problema.
Argus
3

Eu tive o mesmo problema. Eu resolvo. Você pode tentar este código:

[tabBarController setSelectedIndex:1];
[self dismissModalViewControllerAnimated:YES];
Erhan Demirci
fonte
2

O mesmo erro de problema aconteceu comigo quando tentei presentum controlador de visualização filho em vez de seu UINavigationViewControllerpai

Nik
fonte
0

Apenas remova

[tabBarController presentModalViewController:viewController animated:YES];

e mantenha

[self dismissModalViewControllerAnimated:YES];
user170317
fonte
isto dá um aviso obsoleto ... então qual é a alternativa disso?
Kirtikumar A.
Aqui eu usei [blockSelf CC0ViewControllerAnimated: YES completed: nil];
Kirtikumar A.
0

Ao invés de usar:

self.present(viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?)

você pode usar:

self.navigationController?.pushViewController(viewController: UIViewController, animated: Bool)
Wimukthi Rajapaksha
fonte
0

No meu caso, eu estava apresentando o rootViewControllerde um UINavigationControllerquando deveria apresentar o UINavigationControllerpróprio.

Laura Corssac
fonte