“Wait_fences: falha ao receber resposta: 10004003”?

94

Recebo este erro enigmático na primeira vez (e apenas na primeira vez) em que minha visualização é carregada devido à seguinte linha de código:

- (void)viewWillAppear:(BOOL)animated
{
    [textField becomeFirstResponder];
}

Há um atraso perceptível (cerca de 3 a 4 segundos, mesmo no simulador) devido a isso que faz com que meu aplicativo pare de responder. Alguém sabe como consertar isso? Não consigo encontrar nenhuma documentação sobre ele no site da Apple, ou quaisquer soluções aqui ou no Google.

Estranhamente, a situação oposta acontece se eu colocar a linha em -viewDidAppear:vez de -viewWillAppear:; ou seja, em vez de imprimir o erro apenas na primeira vez que o teclado é mostrado e nunca mais, o erro não é impresso na primeira vez, mas sempre depois. Isso está causando uma grande dor de cabeça para mim.

Michael
fonte

Respostas:

103

Substitua -viewDidAppear:, não -viewWillAppear, e certifique-se de ligar [super viewDidAppear:]. Você não deve executar animações quando não estiver na tela ("aparecerá"). E os -viewDidAppear:médicos explicam que você deve ligar superporque eles têm coisas próprias para fazer.

Rob Napier
fonte
Não é tão responsivo quanto eu gostaria (ainda há um pequeno atraso mostrando o teclado a cada vez), mas parece funcionar.
Michael,
1
Eu sei do atraso que você está falando. Eu vi isso em muitos aplicativos. Você pode tentar chamar -becomeFirstResponder antes (em vez de depois) de chamar - [super viewDidAppear:] se ainda não o fez. Isso pode não ter impacto, mas pode fazer com que a animação seja iniciada no mesmo loop de eventos em vez de no próximo. Eu não experimentei isso ainda para confirmar.
Rob Napier,
14
Isso não resolve o problema. Se você lançar um UIAlertSheet em viewDidAppear, depois de chamar [super viewDidAppear: animated], você terminará com a mesma mensagem, todas as vezes. se, no entanto, você jogá-lo para fora depois, digamos, em resposta a uma ação, não há problema. portanto, performWithSelector é provavelmente a maneira de corrigir, ou você pode ignorar a mensagem, de qualquer forma isso parece ser um bug do SDK, não um problema com seu código.
Billy Gray
9
@Billy, lançar um UIAlertSheet antes que as animações sejam feitas provavelmente causaria o mesmo problema. Em qualquer caso, você está colocando uma planilha dentro de viewDidAppear provavelmente é muito cedo e você provavelmente deve usar performSelector: afterDelay: para empurrar o UIAlertSheet para o próximo loop. Isso não é um bug no SDK, embora os detalhes aqui sejam mal documentados. Executar animações em -viewWillAppear era o bug no código original. Em qualquer caso, você não deve ignorar a mensagem. Isso pode levar a artefatos visuais estranhos (um estranho deslizamento lateral da animação).
Rob Napier de
22

Eu estava recebendo um erro semelhante quando rapidamente:

  1. Dispensando uma visualização modal
  2. Atualizando a visualização principal
  3. Apresentando uma nova vista modal

Percebi que só estava conseguindo no simulador e não no aparelho. Além disso, eu estava sendo pego em um loop infinito.

Minha solução foi atrasar a apresentação da nova visão modal. Parece que atualizar rapidamente a hierarquia de visualizações causou algum problema de corrida no código da Apple.

Com isso em mente, tente o seguinte:

     - (void)viewDidAppear:(BOOL)animated{

            [super viewDidAppear:animated];
            [textField performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.1];
  }

Você pode estar tendo problemas para apresentar o teclado para um UITextField que ainda não está na tela. Isso pode estar causando problemas semelhantes aos meus.

Além disso, você faz uma pausa, dando tempo para que a hierarquia seja atualizada antes de apresentar o teclado, apenas para garantir.

Espero que isto ajude.

Corey Floyd
fonte
3
Quanto aos problemas que você estava tendo com os modais, você esperou o modal terminar de dispensar antes de apresentar o novo modal? Em vez de esperar um período arbitrário de tempo e esperar que ele seja concluído, você pode saber substituindo -viewDidDisappear no modalViewController. Isso pode chamar de volta ao -parentViewController do modal ou pode postar uma notificação. A chave é entender que pedir algo para descartar não significa que ele ainda não existe, e você não deve animar coisas umas sobre as outras em geral. -viewWill / DidDisappear é geralmente a melhor maneira de saber com certeza quando as coisas acontecem.
Rob Napier,
A primeira visualização modal foi o seletor de fotos, e eu manejo tudo dentro do método de retorno de chamada do seletor de fotos. Sua direita, eu deveria ter colocado o código para iniciar a próxima visualização modal dentro de viewDdiAppear. essa é uma solução melhor e provavelmente resolveria o problema, independentemente da plataforma.
Corey Floyd
12

Verifique se você está interagindo apenas com a IU no thread principal. Eu fiquei wait_fences: failed to receive reply: 10004003sentado lá esperando um UIAlertView ser mostrado por cerca de 5 segundos porque o código relevante foi executado em um thread de segundo plano. Você pode ter certeza colocando seu código em bloco e enviando-o para o thread principal:

dispatch_async(dispatch_get_main_queue(), ^{
    if (!success) {
        // Inform user that import failed
        UIAlertView * importFailedAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ErrorTitle5", @"Import failed") 
                                                                     message:NSLocalizedString(@"Error5", @"Something went wrong") 
                                                                    delegate:nil 
                                                           cancelButtonTitle:NSLocalizedString(@"OK", nil) 
                                                           otherButtonTitles:nil];
        [importFailedAlert show];
    }
});
diaadélico
fonte
9

Depois de tentar tudo que pude encontrar no Google e nada funcionou, foi isso que resolveu o problema para mim. O importante é que estou fazendo isso no método de delegado willDismissWithButtonIndex. Antes eu estava fazendo isso em outro lugar.

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    [myTextField resignFirstResponder];
    [myTextField removeFromSuperview];  
    [myTextField release];  
}
warehouselabs
fonte
8

Se você tiver a seguinte linha em viewDidLoad, pode causar esta mensagem. Comente a seguinte linha.

[[UIApplication sharedApplication] setStatusBarHidden:YES]; //This line should be commented

(Você pode desativar a barra de status do arquivo plist do aplicativo).

rlcoder
fonte
7

Depois de alguns testes, a grande regra é: "Não execute a animação antes da dispensa da animação ou do show animado.".

Por exemplo:

  • não chame -dismissModalViewControllerAnimated:YESapós o retorno de chamada de delegação de um (aguarde o desaparecimento da visualização de alerta antes de fazer isso usando o retorno de chamada)UIAlertView -alertView:willDismissWithButtonIndex:-alertView:didDismissWithButtonIndex:
  • não tente mostrar o teclado ( becomeFirstResponder) antes que o controlador de visualização esteja na tela.

Coisas ruins podem acontecer.

Espero que seja util ;-)

Nverinaud
fonte
Eu estava usando clickedButtonAtIndex e preenchia vários campos de texto antes de dispensar o alertview. Mudar para didDismissWithButtonIndex certamente ajudou a se livrar desses avisos! Obrigado!
Nitin Alabur
5

Isso funcionou para que o teclado se mostrasse imediatamente, sem animação ou atraso.

Let textFieldSer uma variável de instância de MyViewController(uma subclasse de UIViewController).

Chame [textField becomeFirstResponder]em initWithNibName:bundle:(para uma subclasse de UIViewController) ou initWithStyle:(para uma subclasse de UITableViewController), não em viewDidLoad. Por exemplo:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [textField becomeFirstResponder];
    }
    return self;
}

Ou chame-o logo após a inicialização, mas antes de enviar o UIViewController. Por exemplo:

MyViewController *viewController = [[MyViewController alloc] init];
[viewController.textField becomeFirstResponder];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
ma11hew28
fonte
Interessante. Tem certeza de que isso funciona o tempo todo? Minha preocupação é que você não faça referência view, então não tenho certeza se o arquivo nib foi carregado. Se textFieldfor um IBOutlet, então acho que seria nulo neste momento.
Rob Napier de
5

Você fez [textfield becomeFirstResponder];

E depois de obter o valor de textfield em seu código, faça [textfield resignFirstResponder];. Isso vai te ajudar, eu acho.

Gani
fonte
4

Se você estiver executando o iPhone Simulator 4.0 atual, essa mensagem de erro aparecerá frequentemente ao girar a tela (ou ao animar após girar a tela) acompanhada por um atraso de 1-2 segundos nas animações.

É um bug nesta versão do Simulador e deve ser corrigido em breve.

Matt Gallagher
fonte
obrigado por informações sobre o bug do simulador iOS4. para o mesmo projeto, a wait_fencesmensagem não apareceu no simulador 3.1
ohho
3

Veja aqui para mais informações: http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html

Seu problema está relacionado.

Andrew Johnson
fonte
Obrigado pela ajuda, mas infelizmente não consigo encontrar uma solução para o meu problema nessa página. "Parece que ocorre quando uma subvisualização (por exemplo, UIAlertView) é criada antes de sua visão principal / supervisualização." Isso não deveria estar acontecendo no código acima, certo?
Michael,
3

substituir viewDidappear, não viewWillAppear:

-(void) viewDidAppear:(BOOL) animated
{
 [super viewDidAppear:animated];
 [myTextField becomeFirstResponder];
}
Wagh
fonte
3

Posso simular isso um-a-um por meio deste código UIAlertView.

   UIAlertView *alert = [[UIAlertView alloc]
                   initWithTitle:NSLocalizedString(@"defineTitle",@"defineTitle")
                         message:NSLocalizedString(@"defineBody", @"defineBody")
                        delegate:self
               cancelButtonTitle:NSLocalizedString(@"Ok", @"Ok")
               otherButtonTitles:nil];
   [alert show];

Quando o NSLocalizedString não está definido no arquivo Localizable.strings demorará muito para pesquisar os textos, então o alerta aparecerá e o “wait_fences: failed to receive reply: 10004003” será mostrado.

Para mim, só precisei adicionar os textos aos arquivos Localizable.strings e meus problemas foram resolvidos. Talvez este também seja o caso para outras ocorrências?

Vincent
fonte
1

Também com o UIAlertView. O que resolveu para mim foi pedir demissão conforme abaixo, conforme warehouselabs mencionado anteriormente.

- (void)didPresentAlertView:(UIAlertView *)alertView
{
    [txtListingPassword becomeFirstResponder];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [txtListingPassword resignFirstResponder];
}

Os outros delegados de UIAlertViewDelegate não corrigiram o problema.

Marcus
fonte
1

O problema é que existe uma condição de corrida no código da Apple. Normalmente, isso tem a ver com atualizações incorretas da interface do usuário.

Na minha experiência, você não chamou o super em viewDidAppear, viewWillAppear etc. Ou você tenta exibir um UIAlertView em viewDidLoad ou viewWillAppear.

Quando você adiciona um UIAlertView, a estrutura precisa de uma referência para sua visualização pai. Mas se você estiver em viewWillAppear ou viewDidLoad, a visualização não é realmente exibida ... Você deve considerar mover o código para viewDidAppear, onde a visualização está pronta para ser usada por UIAlertView.

Olá Mundo
fonte
0

O campo de texto está contido nessa visualização ou em alguma outra coisa? Você só pode enviar o 'BecomeFirstRepsonder' para algo que está contido diretamente nessa visualização. Se estiver armazenado em algum outro componente do widget, você não deve definir o status do primeiro respondente neste widget, mas sim no widget que está sendo criado. Por exemplo, se você estiver adicionando o campo de texto a uma visualização de alerta, porque o show acontece de forma assíncrona, ele pode não estar ativo no momento em que você chamar o próximo se torneFirstResponder. (Idealmente, você teria sua própria classe de visualização de alerta e definiria o campo de texto dentro dela, e quando essa visualização recebesse viewDidAppear, você configuraria o campo de texto como o primeiro a responder nesse ponto.)

AlBlue
fonte
0

Eu também recebo a mensagem wait_fences: failed to receive reply: 10004003e meus métodos viewWill...e viewDid...não fazem nada além de enviar mensagens para super. No meu caso, isso acontece quando eu tenho uma UIAlertViewexibição no meu GameViewControllere o usuário pressiona o botão redondo do dispositivo do iPhone e depois retorna ao aplicativo. Isso parece fora de minhas mãos.

SK9
fonte
0

Alertview ou actionsheets devem ser mostrados nos threads principais ... então, se você estiver fazendo conexões síncronas e executando essa operação em outro thread e exibindo alertas com base na saída que você recebeu dessa operação, você receberá esta mensagem de erro wait_fences: failed to receber resposta: 10004003. Você pode fazer algo como ....

[self performSelectotOnMainThread:@selector(handleOutput:) withObject:output waitUntilDone:YES/NO];

e mostra alertas no método handleOutput passando a string de resposta de saída como o parâmetro.

Vishal Singh
fonte
0

A solução está aqui!

Tive o mesmo erro, agora achei a solução, isso pode te ajudar.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
  [self performSelector:@selector(YOUR_METHOD) withObject:nil afterDelay:0.1];
}
SachinVsSachin
fonte