„Wait_fences: nie udało się otrzymać odpowiedzi: 10004003”?

94

Ten tajemniczy błąd pojawia się przy pierwszym (i tylko pierwszym) ładowaniu widoku z powodu następującego wiersza kodu:

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

Występuje zauważalne (~ 3-4 sekundy, nawet na symulatorze) opóźnienie, które powoduje, że moja aplikacja nie reaguje. Czy ktoś wie, jak to naprawić? Nie mogę znaleźć żadnej dokumentacji w witrynie Apple, ani żadnych rozwiązań tutaj ani w Google.

O dziwo, sytuacja odwrotna ma miejsce, gdy wstawię linię -viewDidAppear:zamiast -viewWillAppear:; to znaczy, zamiast drukować błąd tylko przy pierwszym wyświetleniu klawiatury i nigdy więcej, błąd nie jest drukowany za pierwszym razem, ale za każdym razem. To powoduje u mnie duży ból głowy.

Michał
źródło

Odpowiedzi:

103

Nie zastępuj -viewDidAppear:i nie -viewWillAppearzapomnij zadzwonić [super viewDidAppear:]. Nie powinieneś wykonywać animacji, gdy nie jesteś na ekranie („pojawi się”). A -viewDidAppear:doktorzy wyjaśniają, że musisz zadzwonić, superponieważ mają swoje własne sprawy do załatwienia.

Rob Napier
źródło
To nie jest tak czułe, jak bym chciał (za każdym razem pojawia się niewielkie opóźnienie w wyświetlaniu klawiatury), ale wydaje się, że działa.
Michael,
1
Wiem, o jakim opóźnieniu mówisz. Widziałem to w wielu aplikacjach. Możesz spróbować wywołać -becomeFirstResponder przed (zamiast po) wywołaniu - [super viewDidAppear:], jeśli jeszcze tego nie zrobiłeś. Może to nie mieć żadnego wpływu, ale może spowodować rozpoczęcie animacji w tej samej pętli zdarzeń, a nie w następnej. Nie eksperymentowałem jeszcze z tym, aby to potwierdzić.
Rob Napier,
14
To nie rozwiązuje problemu. Jeśli wyrzucisz UIAlertSheet w viewDidAppear, po wywołaniu [super viewDidAppear: animated], za każdym razem otrzymasz tę samą wiadomość. jeśli jednak wyrzucisz go później, powiedz w odpowiedzi na ibakcję, nie ma problemu. więc performWithSelector jest prawdopodobnie sposobem na naprawienie, lub możesz zignorować komunikat, tak czy inaczej wygląda to na błąd SDK, a nie problem z kodem.
Billy Grey
9
@Billy, wyrzucenie arkusza UIAlertSheet przed zakończeniem animacji prawdopodobnie spowodowałoby ten sam problem. W każdym razie umieszczasz arkusz wewnątrz viewDidAppear jest prawdopodobnie za wcześnie i prawdopodobnie powinieneś użyć performSelector: afterDelay:, aby przesunąć UIAlertSheet do następnej pętli. To nie jest błąd w SDK, chociaż szczegóły tutaj są słabo udokumentowane. Wykonywanie animacji w -viewWillAppear było błędem w oryginalnym kodzie. W obu przypadkach nie należy ignorować wiadomości. Może to prowadzić do dziwnych artefaktów wizualnych (dziwne boczne przesuwanie animacji).
Rob Napier
22

Otrzymałem podobny błąd, gdy szybko:

  1. Odrzucanie widoku modalnego
  2. Aktualizacja widoku głównego
  3. Przedstawiamy nowy widok modalny

Zauważyłem, że dostaję to tylko w symulatorze, a nie na urządzeniu. Dodatkowo dałem się złapać w nieskończoną pętlę.

Moim rozwiązaniem było opóźnienie prezentacji nowego widoku modalnego. Wygląda na to, że szybka aktualizacja hierarchii widoków spowodowała pewne utrudnienia w kodzie Apple.

Mając to na uwadze, spróbuj tego:

     - (void)viewDidAppear:(BOOL)animated{

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

Możesz mieć problemy z prezentacją klawiatury dla UITextField, którego jeszcze nie ma na ekranie. Może to powodować problemy podobne do moich.

Ponadto, na wszelki wypadek, zatrzymujesz się, dając czas na aktualizację hierarchii przed prezentacją klawiatury.

Mam nadzieję że to pomoże.

Corey Floyd
źródło
3
Jeśli chodzi o problemy, które miałeś z modami, czy czekałeś na zakończenie zamykania modalu, zanim zaprezentowałeś nowy modal? Zamiast czekać przez dowolny okres czasu i mieć nadzieję, że to się zakończyło, możesz to sprawdzić, zastępując -viewDidDisappear w kontrolerze modalViewController. To może wywołać z powrotem do -parentViewController modala lub może opublikować powiadomienie. Kluczem jest zrozumienie, że proszenie czegoś o odrzucenie nie oznacza, że ​​jeszcze tego nie ma, i ogólnie nie powinieneś animować rzeczy jedna na drugiej. -viewWill / DidDisappear to ogólnie najlepszy sposób, aby wiedzieć na pewno, kiedy coś się wydarzy.
Rob Napier,
Pierwszym widokiem modalnym był selektor zdjęć i obsługuję wszystko w ramach metody wywołania zwrotnego selektora zdjęć. Twoje prawo, powinienem był umieścić kod, aby uruchomić następny widok modalny w ramach viewDdiAppear. jest to lepsze rozwiązanie i najprawdopodobniej rozwiązałoby problem niezależnie od platformy.
Corey Floyd,
12

Sprawdź, czy korzystasz z interfejsu użytkownika tylko w głównym wątku. Dostałem, wait_fences: failed to receive reply: 10004003gdy siedziałem tam i czekałem na wyświetlenie UIAlertView przez około 5 sekund, ponieważ odpowiedni kod został wykonany w wątku w tle. Możesz się upewnić, umieszczając swój kod w bloku i wysyłając go do głównego wątku:

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];
    }
});
diachedelic
źródło
9

Po wypróbowaniu wszystkiego, co mogłem znaleźć w Google i nic z tego nie działało, właśnie to rozwiązało problem. Kluczem jest to, że robię to w metodzie delegata willDismissWithButtonIndex. Wcześniej robiłem to gdzie indziej.

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    [myTextField resignFirstResponder];
    [myTextField removeFromSuperview];  
    [myTextField release];  
}
Warehouselabs
źródło
8

Jeśli masz następujący wiersz w viewDidLoad, może to spowodować ten komunikat. Skomentuj następujący wiersz.

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

(Zamiast tego można wyłączyć pasek stanu w pliku plist aplikacji).

rlcoder
źródło
7

Po kilku testach podstawową zasadą jest: „Nie wykonuj animacji przed zakończeniem animacji lub pokazem animowanym”.

Na przykład:

  • nie wywołuj -dismissModalViewControllerAnimated:YESpo wywołaniu zwrotnym delegacji an (poczekaj, aż zniknie widok alertu, zanim zrobisz to za pomocąUIAlertView -alertView:willDismissWithButtonIndex:-alertView:didDismissWithButtonIndex: zwrotnej)
  • nie próbuj pokazywać klawiatury ( becomeFirstResponder), zanim kontroler widoku nie pojawi się na ekranie.

Mogą się zdarzyć złe rzeczy.

Mam nadzieję, że się przyda ;-)

nverinaud
źródło
Używałem clickedButtonAtIndex i wykonywałem kilka wypełnień pola tekstowego, zanim widok alertów został odrzucony. Przełączenie go na didDismissWithButtonIndex z pewnością pomogło pozbyć się tych ostrzeżeń! Dzięki!
Nitin Alabur
5

Pomogło mi to, aby klawiatura wyświetlała się natychmiast, bez animacji i opóźnień.

Niech textFieldbędzie zmienną instancji MyViewController(podklasą UIViewController).

Zadzwoń [textField becomeFirstResponder]na initWithNibName:bundle:(dla podklasy UIViewController) lub initWithStyle:(dla podklasy UITableViewController), nie viewDidLoad. Na przykład:

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

Lub wywołaj to zaraz po inicjalizacji, ale przed wciśnięciem UIViewController. Na przykład:

MyViewController *viewController = [[MyViewController alloc] init];
[viewController.textField becomeFirstResponder];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
ma11hew28
źródło
Ciekawy. Czy na pewno to działa przez cały czas? Obawiam się, że nie masz odniesienia view, więc nie ma pewności, że plik nib został załadowany. Jeśli textFieldjest to IBOutlet, to myślę, że w tym momencie byłby zerowy.
Rob Napier
5

Uczyniłeś [textfield becomeFirstResponder];

A po uzyskaniu wartości z pola tekstowego w kodzie zrób [textfield resignFirstResponder];. Myślę, że to ci pomoże.

Gani
źródło
4

Jeśli używasz obecnego symulatora iPhone'a 4.0, ten komunikat o błędzie pojawia się często podczas obracania ekranu (lub podczas animacji po obróceniu ekranu), któremu towarzyszy 1-2 sekundowe opóźnienie w animacjach.

Jest to błąd w tej wersji symulatora i powinien zostać wkrótce naprawiony.

Matt Gallagher
źródło
dzięki za informacje o błędzie symulatora iOS4. dla tego samego projektu wait_fenceskomunikat nie pojawił się w symulatorze 3.1
ohho
3

Zobacz tutaj, aby uzyskać więcej informacji: http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html

Twój problem jest powiązany.

Andrew Johnson
źródło
Dzięki za pomoc, ale niestety nie mogę znaleźć rozwiązania mojego problemu na tej stronie. „Wydaje się, że występuje, gdy widok podrzędny (np. UIAlertView) jest tworzony przed jego widokiem nadrzędnym / superwidokiem”. To nie powinno się dziać w powyższym kodzie, prawda?
Michael,
3

nadpisać viewDidappear, a nie viewWillAppear:

-(void) viewDidAppear:(BOOL) animated
{
 [super viewDidAppear:animated];
 [myTextField becomeFirstResponder];
}
Wagh
źródło
3

Mogę zasymulować ten jeden na jednego za pomocą tego kodu UIAlertView.

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

Jeśli ciąg NSLocalizedString nie jest zdefiniowany w pliku Localizable.strings, wyszukiwanie tekstów zajmie zbyt dużo czasu, więc pojawi się alert i zostanie wyświetlony komunikat „wait_fences: failed to get response: 10004003”.

U mnie wystarczyło tylko dodać teksty do plików Localizable.strings i moje problemy zostały rozwiązane. Może dotyczy to również innych sytuacji?

Vincent
źródło
1

Również z UIAlertView. Rozwiązaniem dla mnie była rezygnacja jak poniżej, o czym wspomniałem wcześniej Warehouselabs.

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

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

Inni delegaci UIAlertViewDelegate nie rozwiązali problemu.

Marcus
źródło
1

Problem polega na tym, że w kodzie Apple jest stan wyścigu. Zwykle ma to coś wspólnego z nieprawidłowymi aktualizacjami interfejsu użytkownika.

Z mojego doświadczenia wynika, że ​​albo nie zadzwoniłeś do super in viewDidAppear, viewWillAppear itp. Lub próbujesz wyświetlić UIAlertView w viewDidLoad lub viewWillAppear.

Po dodaniu UIAlertView struktura potrzebuje odwołania do widoku nadrzędnego. Ale jeśli jesteś w viewWillAppear lub viewDidLoad, widok nie jest w rzeczywistości wyświetlany ... Należy rozważyć przeniesienie kodu do viewDidAppear, gdzie widok jest gotowy do użycia przez UIAlertView.

SmallChess
źródło
0

Czy pole tekstowe jest zawarte w tym widoku, czy w czymś innym? Możesz wysłać tylko „getFirstRepsonder” do czegoś, co jest zawarte bezpośrednio w tym widoku. Jeśli jest przechowywany w innym komponencie widżetu, nie należy ustawiać stanu pierwszej osoby odpowiadającej w tym widgecie, ale raczej w tworzonym widgecie. Na przykład, jeśli dodajesz pole tekstowe do widoku alertu, ponieważ pokaz odbywa się asynchronicznie, może nie być uruchomiony do czasu wywołania funkcji getFirstResponder. (Idealnie byłoby, gdybyś miał własną klasę widoku alertów i zdefiniował pole tekstowe w niej, a gdy ten widok otrzyma viewDidAppear, ustaw pole tekstowe jako pierwszy responder w tym momencie).

AlBlue
źródło
0

Otrzymuję również wiadomość, wait_fences: failed to receive reply: 10004003a moje viewWill...i viewDid...metody nie robią nic poza wysyłaniem wiadomości do super. W moim przypadku dzieje się tak, gdy mam UIAlertViewwyświetlanie w moim, GameViewControllera użytkownik zamiast tego naciska okrągły przycisk urządzenia iPhone'a, a następnie wraca do aplikacji. To wychodzi z moich rąk.

SK9
źródło
0

Widok alertów lub arkusze działań powinny być wyświetlane w głównych wątkach ... więc jeśli wykonujesz połączenia synchroniczne i wykonujesz tę operację w innym wątku i wyświetlasz alerty na podstawie danych wyjściowych otrzymanych z tej operacji, otrzymasz komunikat o błędzie wait_fences: failed to otrzymać odpowiedź: 10004003. Możesz zrobić coś takiego ...

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

i pokaż alerty w metodzie handleOutput przekazując wyjściowy łańcuch odpowiedzi jako parametr.

Vishal Singh
źródło
0

Rozwiązanie jest tutaj!

Miałem ten sam błąd, teraz mam rozwiązanie, to może ci pomóc.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
  [self performSelector:@selector(YOUR_METHOD) withObject:nil afterDelay:0.1];
}
SachinVsSachin
źródło