Использование нескольких раскадровки в iOS

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

Storyboard screenshot

Моя mainstoryboard - это вкладка.

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

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

Здесь вывод симулятора.

Simulator

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

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

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

Скриншоты:

Ответ 1

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

Этот парень не только расскажет вам, как создать новую раскадровку в коде, он

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

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

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

Ответ 2

ОП отредактировал свой вопрос, чтобы включить ответ:

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

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

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

Ответ 3

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

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

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

@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

Ответ 4

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

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

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

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

Ответ 5

Как и Xcode 7 (и перенесенный обратно в iOS8), теперь вы можете иметь ссылки на раскадровку. Это было упомянуто в этой WSDC 2015 (он начинает говорить о них около первого часа). В основном все, что вам нужно было сделать, это выбрать ViewController, который вы хотите переместить в отдельный раскадровки, и нажать Редактор- > Рефактор на раскадровку.... Дайте ему имя и вуаля:

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

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

Ответ 6

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

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

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

Ответ 7

Я обнаружил, что если у вас есть имя segue во второй раскадрой, которую вы хотите использовать в вызове для выполненияSegueWithIdenitfier: вы должны установить поле "Идентификатор раскадровки" на вкладке "Идентификация" на исходном ViewController.

Например, если вы предоставили VC, называемый "ViewController1", с помощью segue, называемый "segue1", другому VC, установите "Идентификатор раскадровки" в "ViewController1" на что угодно (скажем, "viewC1" или что-то еще), а затем в ViewController1. m вы можете использовать [self performSegueWithIdentifier: @ "segue1" отправитель: self].

Ответ 8

Xcode 8.2.1

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

отношение из TabBarController в ссылку раскадровки

перетащите соединение из UITabBarController во внешнюю ссылку на Storyboard Reference, добавьте его как отношение "контроллеры представлений". В основной раскадровке он отображается как "Item/square", но во внешнем раскадровке вы должны добавить UITabBarItem и определить имя и изображение /s для вкладки.

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

Инспектор атрибутов, когда выбран Storyboard Reference.

Вам также потребуется предоставить внешнему контроллеру "Идентификатор раскадровки" в своем раскадровке (здесь не показано) и указать его имя в ссылке.