Разница между прямой настройкой представления контроллера и добавлением представления в качестве подпредставления - PullRequest
3 голосов
/ 16 марта 2009

Я только начал изучать target-C и iphone sdk, и у меня есть вопрос, который, я надеюсь, кто-то может помочь пролить немного света.

Какая разница в следующем:

self.view = someView;

и

[self.view addSubView: someView];

Скажем, например, в простом приложении, где у нас есть только один контроллер и один вид контейнера (есть несколько подпредставлений изображения). В чем разница между двумя утверждениями? Причина, по которой я спрашиваю, заключается в том, что я возился с некоторым примером кода и заметил, что представление инициализируется с изображениями в виде подпредставлений, например так:

if (self = [super initWithFrame:CGRectZero])
{
//adds some images as subviews here
}

Насколько я понимаю, initWithFrame: CGRectZero создает кадр с размером [0,0,0,0] (по существу, невидимым).

Когда я непосредственно устанавливаю вид с помощью

self.view = someView;

Я заметил, что вид на самом деле отображает изображение. Но когда я добавляю представление как подпредставление контроллера по умолчанию, это не так. В общем, мой вопрос в том, что происходит за кулисами? Почему первый метод «изменяет размер» фрейма, а второй не делает одно и то же.

Ответы [ 3 ]

9 голосов
/ 16 марта 2009

То, что вы видите на экране вашего iPhone, почти всегда представляет собой иерархию представлений.

Когда вы смотрите, скажем, свой почтовый ящик в Mail, вы видите кучу просмотров. Есть большое сдерживающее представление. [1] В этом есть представление панели навигации, представление таблицы и представление панели инструментов. Внутри панели навигации есть вид кнопки с каждой стороны и вид метки посередине. Внутри табличного представления есть несколько представлений ячеек таблицы, и каждая из этих ячеек имеет несколько представлений меток. Панель инструментов имеет пять видов кнопок. Я мог бы пойти дальше и поговорить о видах внутри этих кнопок и так далее, но я уверен, что вы поняли идею.

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

Каждый вид имеет свою собственную поверхность для рисования. Прямоугольник, образованный этой поверхностью рисования, называется рамкой. Фрейм представления относится к кадру содержащего его представления. Таким образом, если у одного из подпредставлений метки в ячейке таблицы есть рамка (0,0), это означает, что она будет в верхнем левом углу ячейки таблицы, даже если ячейка находится на полпути вниз по экрану.

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

someView.autoresizingMask = UIViewAutoresizingFlexibleWidth
                          | UIViewAutoresizingFlexibleHeight;

(Существует графический способ настройки маски авторазмера в Интерфейсном Разработчике - щелкните значок линейки в окне инспектора и посмотрите раздел «Авторазмер».)

Даже этого недостаточно, если someView не подходит для начала. Для этого настройте его кадр, прежде чем добавить его в качестве подпредставления self.view:

someView.frame = CGRectMake(
                            0, // all the way to the left
                            0, // all the way at the top
                            self.view.frame.size.width, // same width as the root view
                            self.view.frame.size.height, // same height too
                           );

Так зачем вам когда-либо использовать подпредставления, если вам приходится делать все это, что делает для вас корневое представление? Просто: у вас может быть только одно корневое представление, но одного представления почти никогда не достаточно для того, что вам нужно сделать. Если вам действительно нужен только один вид, конечно, вы можете просто установить его в качестве корневого и продолжить свой веселый путь, но, скорее всего, все будет сложнее.

[1] Я немного упрощаю здесь, но сейчас это нормально.

1 голос
/ 16 марта 2009

Когда вы добавляете представление в качестве подпредставления, вам нужно убедиться, что вы фактически добавляете к существующему представлению.

self.view = view устанавливает вид контроллера. Без этого (ни в коде, ни в XIB) вы ничего не увидите, поскольку у контроллера нет представления.

[self.view addSubView: someView] предполагает, что self.view уже установлен. Если этого не произойдет, вы добавляете someview в качестве подпредставления nil, и его никогда не увидят.

По сути, думайте о self.view как о большом контейнере, и все подпредставления - это просто части внутри него. Если вам не нужны подпредставления, установка self.view в UIImageView или UIWebView подойдет. Если вам нужно нужны подпредставления, вам понадобится большое пустое представление контейнера для их размещения.

В вашем случае, я держу пари, что self.view никогда не устанавливается, и вы добавляете изображения в nil.

0 голосов
/ 16 марта 2009

Установка свойства view контроллера «view» только меняет представление, которым оно управляет.

Добавление представления как подпредставления другого представления, фактически добавляет подпредставление под другим представлением.

Это очень разные вещи, так как один настраивает контроллер представления, а другой изменяет иерархию представления.

Как вы думаете, причиной, по которой вы ничего не видели первым, была рамка для добавляемого вами подпредставления: CGRectZero (размер 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...