У мене була подібна проблема - необхідність встановити фрейм "CALayer" при використанні автоматичного макетування з поданнями (у коді, а не IB ).
У моєму випадку я мав дещо заплутану ієрархію, маючи контролер перегляду всередині контролера перегляду. Я опинився на цьому SO-питанні і розглянув підхід використання viewDidLayoutSubviews. Це не спрацювало. На випадок, якщо ваша ситуація схожа на мою, ось що я знайшов ...
Огляд
Я хотів би встановити рамки для CAGradientLayerоператора А , UIViewщо я позиціонував як підвид в межах з UIViewControllerдопомогою обмежень автоматичної компонування.
Викличте підзапис gradientViewта контролер перегляду child_viewController.
child_viewControllerбув контролером перегляду, який я встановив як свого роду повторно використовуваний компонент. Отже, viewкомпонент child_viewControllerкомпонувався у батьківський контролер подання - зателефонуйте parent_viewController.
Коли viewDidLayoutSubviewsз child_viewControllerназивали, то frameз gradientViewще не був встановлений.
(На цьому етапі я рекомендую посипати деякі NSLogтвердження навколо, щоб відчути послідовність створення поглядів у вашій ієрархії тощо).
Тож я перейшов на спробу використання viewDidAppear. Однак через вкладений характер child_viewControllerмене знайшли viewDidAppearне викликали.
(Див. Це запитання SO: viewWillAppear, viewDidAppear не викликається, не запускається ).
Моє поточне рішення
Я додав viewDidAppearу parent_viewControllerі звідти я дзвоню viewDidAppearв child_viewController.
Для початкового завантаження мені потрібно, viewDidAppearоскільки це не відбувається, поки це не буде викликано child_viewController, і всі підпрогляди мають встановлені кадри. Потім я можу встановити рамку для CAGradientLayer...
Я сказав, що це моє поточне рішення, тому що я не особливо ним задоволений.
Після початкового встановлення кадру CAGradientLayer- цей кадр може стати недійсним у разі зміни макета - наприклад, обертаючи пристрій.
Щоб впоратися з цим, я використовую viewDidLayoutSubviewsв child_viewController- щоб зберегти рамку CAGradientLayerвсередині gradientView, правильно.
Це працює, але не відчуває себе добре. (Чи є кращий спосіб?)