1

Куда поместить ручной код макета (или где его инициировать) для определенного дочернего UIView У меня есть, когда сами родительские представления используют автозапуск?где ввести ручной код макета для UIView, где родительские представления используют автозапуск?

Примечание:

  1. код макет для представления необходимо использовать его размеры кадра после любого родительского вида макета, изменения ориентации, признак изменения и т.д.
  2. я попытался с помощью viewWillLayoutSubviews на материнской ViewController, но имели трудности, когда он назывался более одного раза в разы - не могли отследить, почему, однако, НЕ хотят выполнять ручные вычисления раскладки более одного раза, поскольку они обременительны.
  3. Так общий способ для различных сценариев ниже в итоге только один сингл «запуска» ручного макета И в то время, когда все вращения & родительский компоновщик представление было сделано:

Итак:

  • на нагрузке (viewDidLoad)
  • восстановить изображение (например, вид действительно появлялся впоследствии)
  • вращение
  • признака ч Анж

Например я должен смотреть на пути для:

а) родительский вид контроллера для управления этим и определить, когда для отправки «layoutSubviewNow» призыв к моему конкретной точке зрения ребенка (который выходившее это собственный viewcontroller), но в этом случае, как это сделать, или b)

b) оставляя дочернее представление реагировать на «layoutSubview()», а затем имеет делегат для вызова на главный контроллер запросить данные компоновки ?, или

c) аналогично b), но с использованием детского вида s viewWillLayoutSubviews() ", чтобы вызвать, а затем предоставить делегату возможность перезвонить на главный контроллер для запроса данных макета?

или другой?

на самом деле я думаю об этой идее:

г) в главном контроллере родительского вида: иметь переменную viewTransistionedOutstandingAction экземпляра, и использовать его таким образом, что (я) в viewWillTransition установить это верно, то в (II) viewWillLayoutSubviews сделать следующее:

if viewTransistionedOutstandingAction { 
    self.triggerModelChange() 
    viewTransistionedOutstandingAction = false 
} 
+0

Независимо от того, что вы хотите достичь, объясните с помощью скриншота или фрагмента кода. То, что вы объясняете выше, может быть понято вами только потому, что вы знаете, какой результат вы хотите. Просто, если кто-то выберет любой концептуальный ответ, тогда это может быть неправильно для вашей проблемы. –

+0

Хорошо. Может быть, какой-нибудь псевдокод – Greg

+0

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

ответ

1

Это немного непонятно мне, что именно ваши требования, но я могу дать ответ на свой первый вопрос:

Где поставить ручной код макета (или где его запускать) для определенного дочернего UIView У меня есть, когда сами родительские представления используют автозапуск?

Существует ровно одно место в UIView реализации, где вы должны положить любой код макета и что находится внутри метода layoutSubviews().

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

Вы правы, что этот метод можно назвать не один раз, а несколько раз. Это связано с тем, что в некоторых случаях требуется несколько макетов проезда, чтобы вычислить окончательный макет. (Пример: У вас есть представление, высота которого зависит от его ширины супервизора, но высота надстройки зависит от высоты надзора.) Метод layoutSubviews() также может быть вызван вручную из кода, например. вызов setNeedsLayout(), за которым следует layoutIfNeeded() на вид, приведет к вызову layoutSubviews().

Однако система вызывает layoutSubviews() только так часто, как это необходимо (если вручную запустить его снова и снова), то есть, когда текущая раскладка признаны недействительными. Это может быть много причин: вращение устройства, изменения ограничений, изменения в иерархии представлений и т. Д. Но это случаи, когда кадр вашего представления может изменить, и если ваш пользовательский макет зависит от этого кадра, он фактически должен пересмотреть.

По этой причине layoutSubviews() - это только то место, где можно выполнить ручную компоновку, и вы должны воздерживаться от этого в другом месте.


Примечание: Если вы имеете дело с контроллеров отображения вместо простых взглядов соответствующего методом для выполнения ваших обновления макета является viewWillLayoutSubviews() (или viewDidLayoutSubviews(), если вы используете Auto Layout и только хочет внести небольшие изменения после того, как механизм компоновки разрешил ограничения для всех подсмотров).

+0

благодарит Mischa - просто интересно, как люди обращаются к накладным расходам при выполнении вычислений макета (например, я действительно имею собственный пользовательский календарный прокручиваемый календарь) более одного раза повторно вызывается layoutSubviews более одного раза? – Greg

+0

Я не совсем уверен, что вы подразумеваете под «накладными расходами». Есть только два случая: 1. Ваш макет зависит от фрейма представления. Тогда вы _need_, чтобы реагировать на каждое изменение кадра! Да, 'layoutSubviews()' вызывается снова, но нет накладных расходов. 2. Ваш макет не зависит от рамки представления (что почти никогда не бывает). Затем вы можете сделать это только один раз, например.во время инициализации представления. – Mischa

+0

* Дополнение: * Могут быть случаи, когда вызывается 'layoutSubviews()', хотя рамка представления не изменилась. Это единственный случай, когда у вас есть накладные расходы. Вы можете решить эту проблему, сохранив текущий фрейм представления в пользовательском свойстве 'previousFrame' и только выполнив свой собственный код макета, если' frame! = PreviousFrame'. – Mischa

Смежные вопросы