Только на новом iPad 3: wait_fences: не удалось получить ответ: 10004003

Я знаю, что по этому поводу есть много вопросов, но насколько я могу судить, это уникальная ситуация, поэтому я решил, что опубликую ее. Надеюсь, это добавит некоторую информацию, которая, наконец, может дать нам ответ, почему это происходит с нами. Я получаю сообщение об ошибке: wait_fences: не удалось получить ответ: 10004003, когда мое устройство вращается. Анимация моих представлений инициируется:

- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

Я получаю сообщение об ошибке только на новом iPad 3. Я использовал ту же программу на оригинальном iPad и iPhone, начиная с 3GS. Все они не получают ошибку wait_fences, и все они вращаются быстрее, чем iPad 3.

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

Я использовал Time Profiler и обнаружил, что зависание было связано в основном с отрисовкой градиентов: введите описание изображения здесь

Я изменил код для заливки, а не для рисования градиентов, и это решает проблему. Я бы сказал, что проблема заключается в градиентах, за исключением того, что я делаю эту анимацию в других ситуациях (кроме реакции на вращение), и она отлично работает.

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

Я не включил код анимации

Есть идеи относительно того, почему это происходит? Тем более, что это происходит только на iPad 3?

Для тех, кто спросит, это код, который выполняет анимацию. Обычно он будет заключен в блок анимации UIView.

- (void) setFramesForFocusView:(CustomControl *)focusView atX:(CGFloat)x showInput:(BOOL)showInput{
    CGSize bSize = self.bounds.size;
    CGRect fRect = focusView.frame;
    fRect.size.width = bSize.width;

    CGRect iRect;
    if (focusView.inputViewIsSystemKeyboard){
        if (_keyboardRect.origin.y < 0 || _keyboardRect.origin.y >= CGRectGetMaxY(self.bounds) || CGRectIsEmpty(_keyboardRect) || CGRectGetMaxY(_keyboardRect) > CGRectGetMaxY(self.bounds)) return;
        iRect = _keyboardRect;
    } else {
        iRect = (focusView.inputUIView && showInput) ? CGRectMake(0, bSize.height / 2, bSize.width, bSize.height / 2) : CGRectZero;
    }

    CGRect iaRect = focusView.inputAccessoryUIView.frame;
    CGFloat availableFieldHeight = iRect.origin.y - iaRect.size.height;

    iRect.size.width = bSize.width;
    iaRect.size.width = bSize.width;

    if (!showInput){
        iRect.origin.y = bSize.height;
    }
    iaRect.origin.y = iRect.origin.y - iaRect.size.height;

    iRect.origin.x = x;
    iaRect.origin.x = x;
    focusView.inputUIView.frame = iRect;
    focusView.inputAccessoryUIView.frame = iaRect;

    if (focusView.expandInput){
        fRect.origin.y = 0;
        fRect.size.height = availableFieldHeight;
    } else {
        if (focusView.labelPlacement != LabelPlacementTop && focusView.labelPlacement != LabelPlacementBottom){
            fRect.size.height = _currentView.storedFrame.size.height + [focusView.label.text sizeWithFont:focusView.label.font].height; 
        }
        fRect.origin.y = availableFieldHeight - fRect.size.height;
    }
    if (fRect.size.height > availableFieldHeight){
        fRect.origin.y = 0;
        fRect.size.height = availableFieldHeight;
    }
    fRect.origin.x = x;
    [focusView setLabelPlacement:LabelPlacementTop toFrame:fRect];
}

person Aaron Hayman    schedule 07.06.2012    source источник
comment
Тот факт, что это происходит только на iPad 3, в основном говорит о том, что iPad 3 достаточно быстр, чтобы сработать именно из-за проблемы с синхронизацией. Это не означает, что это было правильно на других платформах; только то, что вам повезло на других платформах. Другие ответы, особенно в отношении несоответствующей анимации начала / конца или анимации за пределами экрана, вероятно, все еще применимы.   -  person Rob Napier    schedule 07.06.2012
comment
Я не могу сказать, насколько это актуально, поскольку у меня мало опыта работы с CoreAnimation, но Марко Армент обсудил конкретную проблему iPad 3 с CA renderInContext, которая связана с фанковым графическим оборудованием в нем. Обсуждение можно найти в его подкасте Build and Analyze ep 72, начало в 56:20. В результате, я думаю, iPad стал медленнее. Может что-нибудь почерпнуть можно?   -  person Swizzlr    schedule 07.06.2012
comment
@RobNapier Ага, вы оказались правы. Я трачу так много времени на то, чтобы убедиться, что мой текущий контроллер только анимирует экранные представления, и никогда не думал, что другие контроллеры представлений могут делать свои собственные анимации.   -  person Aaron Hayman    schedule 07.06.2012
comment
@ThomasCatterall Да, я знаком с проблемой renderInContext (и я люблю слушать B&A, обычно вживую :)). Фактически, этот эпизод побудил меня купить iPad 3 для тестирования, что оказалось очень важным. Рад, что я это сделал, мне пришлось заново реализовать много кода, который использовал renderInContext. К счастью, в данном случае проблема не в этом. Я говорю «к счастью», потому что для исправления каждого экземпляра, который мне приходилось заменять «renderInContext», требовалось много кода.   -  person Aaron Hayman    schedule 07.06.2012
comment
Что ж, полезно знать! Рад, что ты разобрался!   -  person Swizzlr    schedule 07.06.2012


Ответы (1)


Что ж, это было быстро. @RobNapier был прав в том, что это проблема времени. Я закомментировал свою анимацию, и ничего себе, там было много других видов, анимированных позади! Несмотря на то, что я явно анимировал только экранные представления, был другой ViewController, который получал события вращения за моими представлениями без моего ... эээ ... знания? Я имею в виду, я должен знать, верно? Я написал код. Сначала я не понял, потому что мой набор представлений покрыл весь экран. К сожалению, для этого потребуется много переписывать. Я использую настраиваемые контроллеры контейнеров и теперь вижу, что мне нужно пересмотреть свою реализацию. Многие вещи без нужды вращаются / анимируются. Но ничего себе ... это ответило на множество вопросов о производительности ....

Обновить

Поэтому я подумал, что проблема, с которой я столкнулся, связана с дополнительными представлениями, анимированными другими контроллерами представлений. Однако, хотя это технически верно, это не так, как я думал или как я думал. Я абсолютно уверен, что никакие другие представления не были анимированы, удалив всю иерархию корневых представлений из окна и заменив ее только контроллером представления, который я хочу повернуть. Это определенно помогло, но не полностью. На самом деле, он просто «опустил планку», чтобы у меня было меньше шансов получить ошибку «wait_fences». Я все же обнаружил, что получаю ошибку, хотя в определенных ситуациях.

Я считаю, что проблема в том, что я использую UIScrollView. Моя реализация имеет переменное количество подчиненных представлений, которыми она управляет. Конкретное представление - это моя собственная индивидуальная реализация UIPickerView, поэтому, как вы можете себе представить, количество представлений, которыми он управляет, может стать довольно большим. Я обнаружил, что если этих подпредставлений становится слишком много, я начинаю получать ошибку «wait_fences».

Получается, что: Если UIScollView является анимированным, он будет анимировать все его подвиды, даже если эти подвиды не отображаются на экране. Это важно. Я скорее подозреваю, что многие люди, которые борются с этой ошибкой, могут этого не осознавать. Каждое из этих скрытых подэкранов подталкивает вас к тому, чтобы столкнуться с ошибкой wait_fences. Решение в моем случае «простое»: я собираюсь преобразовать свой UIScrollView в UITableView. Это будет означать переписывание большого количества кода, но, по крайней мере, я знаю, что скрытые подпредставления будут удалены с экрана и, следовательно, не будут анимированы.

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

Обновление 2

Закончил переписывать свой UIScrollView как tableView, и, похоже, это помогло. Я не получаю никаких задержек и ошибок wait_fences при повороте экрана.

Обновление 2

Так что да, получить wait_fences ошибку на iPad 3 намного проще, чем на любом другом iPad / iPhone. Я просмотрел весь свой код, убедившись, что никогда не анимирую ничего, чего нет на экране, так что эта проблема решена. Я все еще получаю wait_fences ошибку на iPad 3, когда использую «тяжелые» процедуры рисования. Я нашел то, что заставляет меня ударить:

  1. Градиенты: градиенты действительно заставляют процессор работать на экране сетчатки.
  2. Прозрачность: если ваше представление не является непрозрачным, ЦП усердно работает, чтобы определить прозрачные области представления.
  3. Прозрачные цвета: не то же самое, что прозрачность просмотра. Это наложение прозрачных цветов / градиентов друг на друга, чтобы получить «эффект», такой как блеск, высвечивание чего угодно.
  4. Текстуры: я считаю, что использование текстур немного повышает вероятность появления ошибки wait_fences, но не похоже на то, что делают градиенты / прозрачность.
person Aaron Hayman    schedule 07.06.2012