Резюме. Как должен UIViewController
знать размер своего экземпляра UIView при инициализации этого представления?
Специальный метод инициализации для UIView - это метод initWithFrame:(CGRect)frame
. Это устанавливает кадр для вновь созданного UIView. Этот метод можно вызвать из метода load t UIViewController's
, если запрошено представление контроллера вида. Документация UIViewController
указывает на размер подкласса и вида:
При создании представлений для вашего вида иерархии, вы всегда должны устанавливать авторезистирование свойств ваших представлений. Когда контроллер просмотра отображается на экран, его корневой вид обычно измененный в соответствии с доступным пространством, которые могут варьироваться в зависимости от текущую ориентацию окна и наличие других элементов интерфейса например, в строке состояния.
Итак, экземпляр UIViewController
должен установить эти свойства. Пока что так хорошо, UIViewController
пока не должен знать, насколько велика его точка зрения или будет.
Когда запрашивается представление UIViewController
и свойство представления равно 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 (и тем самым предоставляя ему свойство кадра)? Или я что-то упускаю и есть другие возможности?