2011-02-02 4 views
0

У меня возникли проблемы с отладкой, которая, по-видимому, является исключением KVO EXC_BAD_ACCESS в 10.6.6.Исключено из KVO исключение EXC_BAD_ACCESS для свойства position CALayer

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

Все вышеперечисленное отлично работает.

Теперь я добавил эффект резиновой полоски à la iOS, так что когда пользователь прокручивает границы области содержимого, возникает некоторое сопротивление, и когда пользователь позволяет перейти от мыши, содержимое слой привязывается к предельному положению как в размерах x, так и y. Вертикальная привязка работает как шарм. Однако по какой-то причудливой причине любое количество горизонтальной привязки вызывает вышеупомянутое исключение.

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

0 0x7fff810bbc2b в CALayerTransactionFlagsLocation_
1 0x7fff810bbe00 в CALayerMark
2 0x7fff810bd394 в propertyDidChange
3 0x7fff810bcbff в endChange
4 0x7fff810bc9f3 в - [CALayer SetPosition :]
5 0x100038578 in - [MRContextualScrollLayer scrollDidEnd] на MRContextualScrollLayer.m: 280
...

scrollDidEnd является метод, который вызывается, когда пользователь пойдём мыши, и расчет оснастки обратно выполняется для определения того, как переместите слой содержимого для эффекта мгновенного возврата.

Я попытался включить NSZombieEnabled, установив переменную окружения в аргументы исполняемого файла в Xcode, но он не имеет никакого эффекта, то есть никакой дополнительной информации не регистрируется. Это приводит меня к мысли, что проблема не проблема с избыточным объемом памяти, когда к объекту обращаются, чего не должно быть.

Последняя строка в методе scrollDidEnd, что приводит к уведомлению КВО получать отправленные (который затем приводит к аварии) просто:

_contentLayer.position = CGPointMake(_contentLayer.position.x + snapBackOffset.x, 
             _contentLayer.position.y + snapBackOffset.y); 

Кто-нибудь есть какие-либо идеи или полезные советы?

ответ

0

Discovery!

Установка точки останова в методе -dealloc и пошагового, я вижу в Xcode, что

# 3 0x7fff810bf352 в ЦА :: Сделки :: совершать

становится просто обменивались сообщениями перед авария. Это имеет смысл, так как я отключение и повторное включение CA анимации в коде обновления скроллера с использованием шаблона:

// Disable animation temporarily. 
    [CATransaction flush]; 
    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

    // 
    // Update position of CA scrollers. 
    // 

    // Re-enable animation. 
    [CATransaction commit]; 

Если удалить эту CATransaction анимацию отключив логику, все работает отлично.

Похоже, что явные транзакции (такие как шаблон оболочки выше) не поддерживаются в контексте неявных транзакций CALayer, привязанных к KVO, даже через документы говорят, что поддерживаются вложенные транзакции. Вот что добавляет элемент KVO.

Из документации CATransaction:

CATransaction является Core Animation механизма для дозирования несколько операций слоя дерев в атомные обновлений для визуализации дерева. Каждая модификация дерева должна быть частью транзакции . Вложенные транзакции.

Core Animation поддерживает два типа транзакций : неявные транзакции и явные транзакции. Неявные транзакции создаются автоматически , когда дерево слоев изменяется потоком без активной транзакции и фиксируется автоматически, когда следующий цикл цикла потока продолжается. Явные транзакции возникают, когда приложение отправляет класс CATransaction начальное сообщение перед изменением дерева слоев и сообщение об ошибке .

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

0

Правильная переменная окружения не NSEnableZombies, это NSZombieEnabled. Вот почему установка первого ничего не сделала.

Инструмент Инструмент Zombies более полезен. Вы можете перейти прямо из сообщения «zombie messaged» (которое отображается как флаг на временной шкале) для расследования сообщения и зомби в нижней половине окна.

+0

Извинения, это была моя опечатка. В Xcode я использовал правильную переменную среды NSZombieEnabled. Я отредактирую свое оригинальное сообщение, чтобы исправить опечатку. Но спасибо за наконечник инструментов. – Dalmazio