Я изучил подход 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.