«Wait_fences: не удалось получить ответ: 10004003»?

94

Я получаю эту загадочную ошибку в первый раз (и только в первый раз), когда мое представление загружается из-за следующей строки кода:

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

Из-за этого есть заметная задержка (~ 3-4 секунды, даже на симуляторе), из-за которой мое приложение не отвечает. Кто-нибудь знает, как это исправить? Я не могу найти по нему документацию на сайте Apple или какие-либо решения здесь или в Google.

Как ни странно, происходит обратная ситуация, если я вставляю строку -viewDidAppear:вместо -viewWillAppear:; то есть вместо того, чтобы печатать ошибку только при первом отображении клавиатуры и никогда больше, ошибка печатается не в первый раз, а каждый раз после. Это вызывает у меня сильную головную боль.

Майкл
источник

Ответы:

103

Не отменяйте -viewDidAppear:, -viewWillAppearа обязательно звоните [super viewDidAppear:]. Вы не должны выполнять анимацию, когда вы не на экране («появится»). И в -viewDidAppear:документации объясняют, что вы должны позвонить, superпотому что у них свои дела.

Роб Напье
источник
Это не так отзывчиво, как хотелось бы (все еще есть небольшая задержка отображения клавиатуры каждый раз), но, похоже, это помогает.
Майкл
1
Я знаю, о каком лаге вы говорите. Я видел это во многих приложениях. Вы можете попробовать вызвать -becomeFirstResponder до (а не после) вызова - [super viewDidAppear:], если вы еще этого не сделали. Это может не иметь никакого влияния, но может запустить анимацию в том же цикле событий, а не в следующем. Я еще не экспериментировал с этим, чтобы подтвердить.
Роб Напье,
14
Это не решает проблемы. Если вы выбрасываете UIAlertSheet в viewDidAppear после вызова [super viewDidAppear: animated], вы каждый раз получаете одно и то же сообщение. если, однако, вы бросите его потом, скажем, в ответ на действие, нет проблем. так что performWithSelector, вероятно, способ исправить, или вы можете проигнорировать сообщение, в любом случае это похоже на ошибку SDK, а не проблема с вашим кодом.
Билли Грей,
9
@Billy, бросок UIAlertSheet до завершения анимации, скорее всего, вызовет ту же проблему. В любом случае, вы помещаете лист внутри viewDidAppear, вероятно, слишком рано, и вам, вероятно, следует использовать performSelector: afterDelay:, чтобы переместить UIAlertSheet в следующий цикл. Это не ошибка SDK, хотя подробности здесь плохо документированы. Выполнение анимации в -viewWillAppear было ошибкой в ​​исходном коде. В любом случае не игнорируйте сообщение. Это может привести к появлению необычных визуальных артефактов (странное скольжение анимации вбок).
Роб Нэпир,
22

Я получал аналогичную ошибку, когда быстро:

  1. Отказ от модального представления
  2. Обновление основного вида
  3. Представляем новый модальный вид

Я заметил, что получаю это только в симуляторе, а не на устройстве. Вдобавок я попадал в бесконечный цикл.

Мое решение заключалось в том, чтобы отложить представление нового модального представления. Похоже, что быстрое обновление иерархии представлений вызвало некоторую состязательность в коде Apple.

Имея это в виду, попробуйте следующее:

     - (void)viewDidAppear:(BOOL)animated{

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

У вас могут возникнуть проблемы с отображением клавиатуры для UITextField, который еще не отображается на экране. Это может вызывать проблемы, похожие на мои.

Кроме того, на всякий случай вы делаете паузу, давая иерархии время для обновления, прежде чем показывать клавиатуру.

Надеюсь это поможет.

Кори Флойд
источник
3
Что касается проблем, которые у вас возникли с модальными окнами, вы ждали, пока модальное окно завершит удаление, прежде чем представить новое модальное окно? Вместо того, чтобы ждать произвольный период времени и надеяться, что он завершится, вы можете узнать об этом, переопределив -viewDidDisappear в modalViewController. Это может вызвать обратный вызов модального -parentViewController или отправить уведомление. Ключ в том, чтобы понять, что просьба отклонить что-то еще не означает, что это еще не все, и вам не следует анимировать объекты друг над другом в целом. -viewWill / DidDisappear - лучший способ узнать наверняка, когда что-то случится.
Роб Нэпьер,
Первым модальным представлением было средство выбора фотографий, и я обрабатываю все в методе обратного вызова средства выбора фотографий. Ваше право, я должен был разместить код для запуска следующего модального представления в viewDdiAppear. это лучшее решение, которое, скорее всего, решит проблему независимо от платформы.
Кори Флойд,
12

Убедитесь, что вы взаимодействуете только с пользовательским интерфейсом в основном потоке. Я получил, wait_fences: failed to receive reply: 10004003пока сидел и ждал, пока отобразится UIAlertView около 5 секунд, потому что соответствующий код был выполнен в фоновом потоке. Вы можете убедиться в этом, поместив свой код в блок и отправив его в основной поток:

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];
    }
});
диаходелический
источник
9

После того, как я попробовал все, что смог найти в Google, и ничего не заработало, это решило проблему для меня. Ключ в том, что я делаю это в методе делегата willDismissWithButtonIndex. Раньше я делал это в другом месте.

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    [myTextField resignFirstResponder];
    [myTextField removeFromSuperview];  
    [myTextField release];  
}
склады
источник
8

Если у вас есть следующая строка в viewDidLoad, это может вызвать это сообщение. Прокомментируйте следующую строку.

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

(Вместо этого вы можете отключить строку состояния из файла plist приложения).

rlcoder
источник
7

После нескольких тестов большое правило гласит: «Не выполняйте анимацию перед анимированным увольнением или анимационным шоу».

Например:

  • не вызывайте -dismissModalViewControllerAnimated:YESпосле обратного вызова делегирования (дождитесь исчезновения из представления предупреждения, прежде чем делать это с помощью обратного вызова)UIAlertView -alertView:willDismissWithButtonIndex:-alertView:didDismissWithButtonIndex:
  • не пытайтесь показать клавиатуру ( becomeFirstResponder), пока ваш контроллер представления не появится на экране.

Могут случиться плохие вещи.

Надеюсь, это будет полезно ;-)

Нверино
источник
Я использовал clickedButtonAtIndex и заполнял несколько текстовых полей до того, как предупреждение было закрыто. Переключение на didDismissWithButtonIndex определенно помогло избавиться от этих предупреждений! Спасибо!
Нитин Алабур
5

Это помогло мне заставить клавиатуру показать себя немедленно, без анимации и задержки.

Позвольте textFieldбыть переменной экземпляра MyViewController(подкласса UIViewController).

Позвоните [textField becomeFirstResponder]в initWithNibName:bundle:(для подкласса UIViewController) или initWithStyle:(для подкласса UITableViewController), а не в viewDidLoad. Например:

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

Или вызовите его сразу после инициализации, но перед нажатием UIViewController. Например:

MyViewController *viewController = [[MyViewController alloc] init];
[viewController.textField becomeFirstResponder];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
ma11hew28
источник
Интересный. Вы уверены, что это работает все время? Меня беспокоит то, что вы не ссылаетесь view, поэтому не уверен, что файл пера загружен. Если textFieldэто IBOutlet, то я думаю, что на данном этапе он будет нулевым.
Роб Напье
5

Ты сделал [textfield becomeFirstResponder];

И после того, как вы получите значение из текстового поля в своем коде, сделайте [textfield resignFirstResponder];. Думаю, это вам поможет.

Гани
источник
4

Если вы используете текущую версию iPhone Simulator 4.0, это сообщение об ошибке часто появляется при повороте экрана (или при анимации после поворота экрана), сопровождаемой задержкой в ​​1-2 секунды в анимации.

Это ошибка в данной версии симулятора, и ее вскоре следует исправить.

Мэтт Галлахер
источник
спасибо за информацию об ошибке симулятора iOS4. для того же проекта wait_fencesсообщение не
появилось в
3

См. Здесь для получения дополнительной информации: http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/17373-wait_fences-failed-receive-reply-10004003-a.html

Ваша проблема связана.

Эндрю Джонсон
источник
Спасибо за помощь, но, к сожалению, я не могу найти решение своей проблемы на этой странице. «Кажется, это происходит, когда подвид (например, UIAlertView) создается до его родительского / суперпредставления». Этого не должно происходить в приведенном выше коде, верно?
Майкл
3

переопределить viewDidappear, а не viewWillAppear:

-(void) viewDidAppear:(BOOL) animated
{
 [super viewDidAppear:animated];
 [myTextField becomeFirstResponder];
}
Wagh
источник
3

Я могу смоделировать это один на один с помощью этого кода UIAlertView.

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

Когда NSLocalizedString не определены в файле Localizable.strings, поиск текстов займет слишком много времени, поэтому будет показано предупреждение и «wait_fences: не удалось получить ответ: 10004003».

Мне достаточно было добавить тексты в файлы Localizable.strings, и мои проблемы были решены. Может быть, это относится и к другим случаям?

Винсент
источник
1

Также с UIAlertView. Что решило это для меня, так это отставка, как показано ниже, как упоминалось ранее.

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

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

Другие делегаты UIAlertViewDelegate не устранили проблему.

Маркус
источник
1

Проблема в том, что в коде Apple есть состояние гонки. Обычно это связано с неправильными обновлениями пользовательского интерфейса.

По моему опыту, вы либо не вызывали super в viewDidAppear, viewWillAppear и т. Д., Либо пытаетесь отобразить UIAlertView в viewDidLoad или viewWillAppear.

Когда вы добавляете UIAlertView, фреймворку требуется ссылка на ваше родительское представление. Но если вы находитесь в viewWillAppear или viewDidLoad, представление на самом деле не отображается ... Вам следует подумать о перемещении кода в viewDidAppear, где представление готово для использования UIAlertView.

Привет мир
источник
0

Содержится ли текстовое поле в этом представлении или в чем-то еще? Вы можете отправить «статьFirstRepsonder» только тому, что содержится непосредственно в этом представлении. Если он хранится в каком-либо другом компоненте виджета, вы не должны устанавливать статус первого респондента в этом виджете, а скорее в создаваемом виджете. Например, если вы добавляете текстовое поле в представление предупреждений, поскольку шоу происходит асинхронно, оно может не быть активным к тому времени, когда вы вызовете метод beginFirstResponder. (В идеале у вас должен быть собственный класс представления предупреждений и определение текстового поля в нем, и когда это представление получит viewDidAppear, вы должны установить текстовое поле в качестве первого респондента в этот момент.)

AlBlue
источник
0

Я также получаю сообщение wait_fences: failed to receive reply: 10004003и мои viewWill...и viewDid...методы ничего не делать , но отправлять сообщения super. В моем случае это происходит, когда у меня есть UIAlertViewпоказ, GameViewControllerи пользователь вместо этого нажимает круглую кнопку устройства iPhone, а затем возвращается в приложение. Это выглядит не из моих рук.

SK9
источник
0

Alertview или таблицы действий должны отображаться в основных потоках ... поэтому, если вы создаете какие-либо синхронные соединения и выполняете эту операцию в другом потоке и показываете предупреждения на основе выходных данных, полученных от этой операции, вы получите это сообщение об ошибке wait_fences: failed to получить ответ: 10004003. Вы можете сделать что-то вроде ....

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

и показывать предупреждения в методе handleOutput, передавая строку выходного ответа в качестве параметра.

Вишал Сингх
источник
0

Решение здесь!

У меня была такая же ошибка, теперь у меня есть решение, это может вам помочь.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
  [self performSelector:@selector(YOUR_METHOD) withObject:nil afterDelay:0.1];
}
Сачин против Сачина
источник