Subviews layer transform и layoutSubviews

мой вопрос связан с

UIView/CALayer: преобразование триггеров layoutSubviews в режиме просмотра

Где сообщается, что из ответа TSI от apple:

Как правило, изменение геометрического свойства вида (или слоя) будет вызвать каскад недействительности макета вверх по иерархии представлений поскольку родительские представления могут иметь ограничения Auto Layout, связанные с модифицировано ребенок. Обратите внимание, что автоматический макет активен в определенной форме независимо от того, явно ли вы включили его.

В моем случае у меня очень простая иерархия представлений, где представление A содержит представление B

В layoutSubviews A я устанавливаю кадр B.

Когда я выполняю анимацию (трансформирование и непрозрачность) на уровне поддержки B, иногда вызывается layoutSubviews из A. Это, очевидно, проблема, потому что я устанавливаю кадр B в layoutSubviews A, и это прерывает анимацию.

Как я могу избежать этого конфликта между макетом B и анимацией?

Ответ 1

Я обнаружил, что можно решить эту проблему разными способами:

1) Временно сохранять преобразование, изменять кадр и повторно применять преобразование:

[super layoutSubviews];

//backup the transform value before the layout
CATransform3D transform = self.internalView.layer.transform;

//Set identity and update all the necessary frames
self.internalView.layer.transform = CATransform3DIdentity;
self.internalView.frame = self.bounds;

//set back the transform
self.internalView.layer.transform = transform;

2) Измените границы и центр представления, не касаясь кадра. Границы и центр, похоже, не влияют на трансформацию. Имеют смысл, потому что кадр вычисляется внутренне считывает границы слоя, положение, преобразование, точку привязки.

self.internalView.bounds = self.bounds;
self.internalView.center = CGPointMake(floorf(CGRectGetWidth(self.bounds)/2.0f),        floorf(CGRectGetHeight(self.bounds)/2.0f));

3) Apple в TSI (см. здесь UIView/CALayer: трансформирование триггеров layoutSubviews в супервизии) предлагает

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

Если это не работает, создайте какой-либо механизм для дорогостоящий метод макета, когда он на самом деле (или не должен) Работа. Это может быть свойство, которое вы устанавливаете при внесении изменений относятся к преобразованиям."

4) Я также экспериментировал полностью отключить автозапуск для подпрограмм моего пользовательского представления. Вы можете прочитать эту действительно хорошую статью из obj.io, где объясняется, что если вы удалите вызов [super layoutSubviews] из реализации layoutSubviews, вы отказываются от автозапуска для вашего пользовательского представления и всех его подзонов.

Отступ в том, что вы должны знать, что в случае, когда вы добавляете в качестве подзадача представление со сдерживаниями, система автоопределения будет создавать исключение, подобное этому:

*** Завершение приложения из-за неотображенного исключения "NSInternalInconsistencyException", причина: "Автоматический макет все еще требуется после выполнения -layoutSubviews. Реализация MyView -layoutSubviews нужно вызвать super. '

Решение 1 и 2 хороши, если у вас простая логика компоновки. Если ваша логика макета экспансивна, вы можете реализовать 3 или 4 и рефери к этому другому вопросу UIView/CALayer: Трансформировать триггеры layoutSubviews в режиме просмотра