Резюме: Как UIViewController
должен знать размер своего экземпляра UIView при инициализации этого представления?
Выделенным методом инициализации для UIView является initWithFrame:(CGRect)frame
метод. Это устанавливает рамку для вновь созданного UIView. Этот метод может быть вызван из метода UIViewController's
loadView, если запрашивается представление этого представления контроллера. Документация UIViewController
указывает на подклассы и размер представления:
При создании представлений для вашего вида
иерархия, вы всегда должны установить
автоматическое изменение размеров ваших просмотров.
Когда контроллер представления отображается на
экран, его корневой вид обычно
изменен в соответствии с доступным пространством,
которая может варьироваться в зависимости от
текущая ориентация окна и
наличие других элементов интерфейса
такие как строка состояния.
Итак, экземпляр UIViewController
должен установить эти свойства. Пока все хорошо, UIViewController
пока не нужно знать, насколько велик его вид или будет.
Когда запрашивается представление UIViewController
и свойство view равно nil, вызывается метод loadView контроллера представления. Теперь возникает проблема, поскольку UIView
необходимо инициализировать, но контроллер представления все еще не знает, каким должен быть размер представления. Насколько большой вы должны инициализировать это представление? Где в коде вы определяете размер вида?
Вы можете инициализировать представление нулевым прямоугольником (CGRectZero
):
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}
И пусть вызывающая сторона устанавливает рамку вида так:
UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);
Это запрашивает представление из контроллера представления (viewController.view) и таким образом загружает его представление с помощью метода loadView. Этот метод loadView инициализирует представление с CGRectZero
. Затем вызывающая сторона устанавливает свой кадр (view.frame = ...)
Дело в том, что свойство frame в представлении задается дважды, что может привести к еще большей двойной работе, если ваш пользовательский UIView
выполняет какой-то расширенный макет в методе setFrame (например, размещает и изменяет размеры подпредставлений). Вы можете предотвратить это, создав специальный метод инициализации для UIViewController
, который уже запрашивает у вызывающего абонента CGRect, который вы бы сохранили в ivar. Во время вызова метода loadView вы используете этот ivar для создания представления.
Какой хороший путь сюда? Или дважды установить фрейм представления (инициализировать с помощью CGRectZero
и установить впоследствии), или дать UIViewController
новый метод инициализатора с CGRect (и, таким образом, присвоить ему свойство frame)? Или я что-то упустил и есть ли другие возможности?