Использование нескольких раскадровок в iOS - PullRequest
74 голосов
/ 28 ноября 2011

Моя цель - создать приложение с вкладками, тогда представление для каждой из вкладок построено в отдельных раскадровках.

Storyboard screenshot

Моя основная панель - это вкладка.

Затем я создаю вторичную раскадровку (раскадровку № 2) с 2 контроллерами вида. Первый контроллер вида (также отмеченный как начальный) имеет кнопку и переходит (модальный) к 2-му виду. First view controller

Мне удалось загрузить представление путем создания подклассов и переопределения loadView из раскадровки № 2. loadView override

Вот выходные данные симулятора.

Simulator

При нажатии на кнопку «щелкни меня» я получаю EXC_BAD_ACCESS. Segue не работает, похоже, что вторая раскадровка загружается не полностью.

Кто-нибудь пытался сделать это раньше и заставить его работать? Есть видео на YouTube от SkillMaster.net, но он не демонстрирует, работает ли переход под вторичной раскадровкой. видео здесь: http://youtu.be/D4_twoYvB4M

Спасибо за любой вклад и помощь!

Скриншоты:

Ответы [ 9 ]

79 голосов
/ 01 октября 2012

Это лучшие статьи, которые я видел на разных раскадровках.

Мало того, что этот парень говорит вам, как создать новую раскадровку в коде, он

  • рекомендует на практике несколько раскадровок (более модульный код)
  • обсуждается, когда использовать xibs против раскадровок (xibs хранит представления, storboards основаны на контроллерах)
  • предоставляет класс для связывания раскадровок с сегментами на github

Обратите внимание, что этот последний пункт важен, потому что ключевым недостатком нескольких раскадровок является то, что вы обычно не можете связать их с segues, но библиотека робов позволяет это с небольшим количеством выдумки

Также см. Обсуждаемое здесь

44 голосов
/ 15 декабря 2011

ОП отредактировал свой вопрос, включив в него ответ:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];

initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:initialHelpView animated:YES];

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

19 голосов
/ 31 октября 2013

Я изучил подход RBStoryboardLink , предложенный Rhubarb. Эта реализация заменяет свойства контроллера вида, что выглядит странно. Я считаю, что нашел способ избежать этого. Вот демонстрационный проект .

Навигационные контроллеры

Контроллеры навигации могут просто установить контроллер представления, на который ссылаются, как root. Реализация такого контроллера представления может выглядеть так:

@interface ExternNavigationController : UINavigationController

@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;

@end

@implementation ExternNavigationController

- (void)awakeFromNib
{
    NSAssert(self.storyboardName, @"storyboardName is required");

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:self.storyboardName bundle:nil];
    UIViewController *vc = self.sceneIdentifier
        ? [storyboard instantiateViewControllerWithIdentifier:self.sceneIdentifier]
        : [storyboard instantiateInitialViewController];

    self.viewControllers = @[vc];
}

@end

Просмотр контроллеров

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

@interface ExternStoryboardSegue : UIStoryboardSegue

@end

@implementation ExternStoryboardSegue

- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(ExternViewController *)destination
{
    NSAssert(destination.storyboardName, @"storyboardName is required");

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:destination.storyboardName bundle:nil];
    UIViewController *vc = destination.sceneIdentifier
        ? [storyboard instantiateViewControllerWithIdentifier:destination.sceneIdentifier]
        : [storyboard instantiateInitialViewController];

    return [super initWithIdentifier:identifier source:source destination:vc];
}

- (void)perform
{
    [[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:YES];
}

@end

ExternViewController используется в качестве заполнителя и содержит необходимые для свойств подстановки (storyboardName и sceneIdentifier).

@interface ExternViewController : UIViewController

@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;

@end

@implementation ExternViewController

@end

Нам нужно установить эти свойства и пользовательский класс для контроллера представления заполнителя. А также связать контроллер представления с ExternStoryboardSegue.

IB screenshot

16 голосов
/ 24 апреля 2012

Из одного из моих файлов XIB я перемещаюсь в более сложную часть графического интерфейса, и для этой части я использую раскадровку.Таким образом, кнопка в моем XIB перейдет к раскадровке.Код, который у меня есть для этого:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardIdentifier" bundle:nil];
UIViewController* myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];

[self.navigationController pushViewController:myStoryBoardInitialViewController animated:YES];

Это успешно подтолкнет мою StoryBoard к представлению.Вышеприведенный код вызывается из действия кнопки «Touch Up Inside».

9 голосов
/ 15 октября 2015

Начиная с Xcode 7 (и перенесена обратно на iOS8), теперь вы можете иметь ссылки на раскадровку. Это было упомянуто в этом WWDC 2015 сеансе (он начинает говорить о них примерно в первый час). По сути, все, что вам нужно было сделать, это выбрать ViewController, который вы хотите переместить на отдельную раскадровку, и нажать Editor-> Refactor to Storyboard ... . Дайте ему имя и вуаля:

enter image description here

Обратите внимание, что если у вас есть ВК, которые перемещены на новую раскадровку, и на которые нет ссылок за ее пределами (какими они должны быть), вы должны удалить их ссылки из main.storyboard (расслабьтесь, они останутся во вновь созданной раскадровке). Вы удаляете только ссылки на них).

7 голосов
/ 28 ноября 2011

Документы Apple говорят, что у вас может быть несколько раскадровок.К сожалению, они не вдавались в подробности того, как это сделать.Как вы узнали, Interface Builder вам не поможет, поэтому вам придется делать это в коде.Это работает так же, как загрузка XIB:

[UIStoryboard storyboardWithName:@”MyNewStoryboard” bundle:myBundle]

Сказав это, если вы не «хотите одну большую / раздутую раскадровку», как вы сказали в своем комментарии, тогда XIB действительно являются подходящим способом.Это «преимущество» является преимуществом: все переходы между венчурными капиталами расположены в одном месте.Наличие нескольких раскадровок действительно позволяет поддерживать несколько разных и не связанных между собой потоков через ваше приложение: например, одну раскадровку для сложного потока конфигурации и другую для основного потока пользователей.

2 голосов
/ 17 января 2017

Xcode 8.2.1

Вы можете ссылаться на контроллер представления во внешней раскадровке.

relationship from TabBarController to Storyboard Reference

перетащите соединение изUITabBarController к внешней ссылке на раскадровку, добавьте ее как отношение «просмотр контроллеров».В основной раскадровке он отображается как «Предмет / квадрат», но во внешней раскадровке вы должны добавить UITabBarItem и определить имя и изображение / ы для вкладки.

enter image description here

Атрибут инспектора при выборе Storyboard Reference.

Вам также необходимо присвоить внешнему контроллеру «Storyboard ID» в его раскадровке (здесь не показан) , и укажите его имя в ссылке.

2 голосов
/ 23 февраля 2013

Я обнаружил, что если у вас есть именованный переход во второй раскадровке, которую вы хотите использовать при вызове executeSegueWithIdenitfier: вы должны установить поле «Storyboard ID» на вкладке «Identity» в исходном ViewController.

Например, если вы дали VC с именем "ViewController1" с переходом с именем "segue1" другому VC, установите для идентификатора "Storyboard ID" ViewController1 "любое значение (скажем," viewC1 "или что-то еще), а затем в ViewController1. m вы можете использовать [self executeSegueWithIdentifier: @ "segue1" sender: self].

1 голос
/ 23 мая 2018

Выполните следующие шаги для решения этой задачи:

Шаг 1 : поиск компонентов Storyboard Reference (см. Снимок экрана)

Шаг 2 : выберите новую ссылку на раскадровку. (См. Снимок экрана)

Шаг 3 : укажите новое название раскадровки и идентификатор идентификатора контроллера начального вида (см. Снимок экрана)

enter image description here

Сборка и запуск. Это будет работать.

...