Пользовательские представления с раскадровкой


96

На сложных экранах (контроллеры представления) я обычно разделял все на более мелкие части (я называю их виджетами). Эти виджеты состоят в основном из a MyWidget.hи MyWidget.mфайла, а также MyWidget.xibфайла, где корневым элементом является a, UIViewа класс MyWidget является владельцем файла UIView. В инициализации этого виджета я делаю loadNibNamed.

Затем в моем контроллере представления я делаю элемент [[MyWidget alloc] init], который добавляю в главное представление контроллера представления в качестве вспомогательного представления. Пока это работает отлично.

Теперь мне интересно, как сделать то же самое с раскадровкой, потому что я действительно не могу начать перетаскивать UIViewкуда-то, мне всегда нужно начинать с UIViewController, чего я не хочу.

Если нет возможности сделать это с помощью раскадровки, могу ли я просто сделать это старым способом, используя раскадровку для моих основных экранов и переходов, и использовать отдельный файл .xib для определения пользовательских представлений?


Вы хотите создавать xibs для ваших контроллеров представления отдельно, а не в раскадровке?
tipycalFlow

Вы нашли решение этого?
aryaxt

@aryaxt: я использую смесь раскадровки и xib. Раскадровка для основных экранов и xib только с UIView в качестве корня для сложных представлений или виджетов. Так что это не совсем ответ на мой исходный вопрос (с помощью раскадровки), но в основном я делаю то же самое, что и раньше.
znq 02

в наши дни просто используйте представление контейнера , это действительно так просто .. stackoverflow.com/questions/23399061/…
Fattie

Ответы:


189

Помещение виджета / представления в отдельный файл .xib работает и подходит, особенно если вы можете захотеть ссылаться на то же представление из нескольких контроллеров представления.

Однако иногда вам все же нужно увидеть дополнительное представление / виджет в той же раскадровке, и это возможно. Вот как это сделать:

  1. Выберите контроллер представления в IB (щелкните черную полосу под представлением), затем перетащите UIView из библиотеки объектов на черную полосу:

    введите описание изображения здесь

  2. Когда представление находится на черной полосе, оно создается, как и любое другое представление в IB, но просто не добавляется в вашу иерархию представлений, пока вы не сделаете это в коде. При необходимости измените класс представления, чтобы он соответствовал вашему собственному подклассу:

    введите описание изображения здесь

  3. Вы можете подключить его к своему контроллеру представления, как и любое другое представление: введите описание изображения здесь

  4. Добавленное представление отображается в структуре документа, и вы также можете подключать действия и ссылки:

    введите описание изображения здесь


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

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

Другой обходной путь более привередлив, но я предпочитаю его, потому что он позволяет мне видеть все мои представления одновременно:

  1. Перетащите UITableView из библиотеки объектов в только что добавленное представление.

  2. Затем перетащите UITableViewCell в этот UITableView.

    введите описание изображения здесь

  3. Как только вы это сделаете, ваше представление волшебным образом появится сбоку, но у вас есть UITableView, который вам не нужен. Вы можете либо изменить его размер до 0x0, либо удалить его, и ваш UIView (обычно) останется видимым.

  4. Иногда вторичный вид снова скрывается в IB. Вы можете повторить вышеуказанные шаги, если удалили UITableView или если UITableView все еще находится в иерархии, вам просто нужно щелкнуть UITableViewCell, и представление появится снова.

Второй метод работает для UIViews, но не так хорошо для UIToolbars и невозможен для UIButtons, поэтому самое чистое решение, которое я нашел, когда вам нужно включить много разных подвидов, - это прикрепить один вторичный UIView к вашему контроллеру представления в качестве контейнера, который никогда не отображается, поместите туда все ваши вторичные представления и используйте трюк UITableViewCell, чтобы сделать все видимым. Я изменяю размер своего фиктивного UITableView на 0x0, чтобы сделать его невидимым. Вот скриншот того, как все это выглядит вместе:

введите описание изображения здесь


Март 2013 года, мне не нужно было этого делать - вы должны полностью игнорировать черную полосу и перетаскивать свое представление непосредственно в основное представление, и оно отлично работает (Xcode 4.5+)
Адам

Можно ли повторно использовать этот пользовательский uivew на том же ViewController - если я напр. понадобилось два кастомных uivews - А если как?
Мортен Густафссон,

2
Блин, я предпочитаю просто создать отдельный xib. Я, наверное, всего этого не вспомню, когда через 6 месяцев мне придется обновлять приложение.
Сэнди

Хотя это отличный ответ, я случайно нашел другой способ получше. При подключении розеток к фактическим компонентам просмотра. Если немного навести курсор на компонент такого внутреннего вида - он всплывает для облегчения выбора. Затем вы видите это на раскадровке ...
Одед Бен Дов

7
Хотя это невероятно замечательный исторический ответ, на самом деле он полностью устарел. Apple устранила всю проблему, представив «представления контейнера», которые теперь являются центральной, базовой вещью, которую вы делаете при создании приложений - все это постоянно «представление контейнера». Слава богу, теперь это очень просто!
Fattie

11

Если вы просто хотите сделать свои контроллеры представлений где-то еще (а не на своей раскадровке), то есть довольно простой способ сделать это:

1) Создайте свои CustomViewControllers ( abcdControllerв коде, который я пробовал) с их индивидуальными xibs, как обычно.

2) Добавьте UIViewController(или что-то еще, что было вашим суперклассом CustomViewController) в раскадровку.

3) Установите CustomClass CustomViewControllerвместо, UIViewControllerкак показано здесь:

введите описание изображения здесь

4) Наконец, viewDidLoadзагрузите кастом, xibи все готово.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSBundle mainBundle] loadNibNamed:@"abcdController" owner:self options:nil];
    // Do any additional setup after loading the view from its nib.
}

3
Спасибо за очень подробный ответ, но на самом деле я ищу не настраиваемый контроллер представления, а настраиваемое представление (виджет), которое добавляется к стандартному UIViewController. Таким образом, проблема не в контроллере представления, но мне было интересно, как лучше всего создавать собственные виджеты. Либо A) сделайте это, как я делал раньше, с файлом .xib, либо B) какой-нибудь другой подход, которого я пока не знаю :-)
znq

1
Хм ... Думаю, я получил то, что ты хочешь. В основном вы хотите обрабатывать несколько представлений с помощью одного контроллера, верно? Я не могу придумать другого пути, кроме как loadNibNamedв этом случае ... XO
tipycalFlow

Это решило для меня эту проблему: stackoverflow.com/questions/11047991/… Однако вместо viewDidLoad я использовал loadView ...
Моркром

1
Чтобы повторить, это все (слава богу!) Полностью устарело теперь, когда здесь есть представления контейнеров. Просто щелкните вид контейнера, и все готово
Fattie

1

Я думаю, вы можете сделать что-то подобное, чтобы получить экземпляр определенного контроллера просмотра из раскадровки и использовать вид поверх него.

ex:
MyViewController* myViewController = [[UIStoryboard storyboardWithName:@"Main"  bundle:nil] instantiateViewControllerWithIdentifier:@"myViewController"];
UIView* view = myViewController.view; //Get the view from your StoryBoard.

Надеюсь это поможет

Спасибо виджай

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.