我研究了 Rhubarb 建议的 RBStoryboardLink 方法。
这个实现替代了看起来很奇怪的视图控制器的属性。我相信我已经找到了避免这种情况的方法。 Here is the demo project.
导航控制器
导航控制器可以将一个引用的视图控制器设置为根。这种视图控制器的实现可能如下所示:
@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
视图控制器
当您想要推送在外部故事板中定义的视图控制器时,问题就开始了。复制属性时就是这种情况。取而代之的是,我们可以实现一个自定义 segue,它将一个假目标控制器替换为来自外部故事板的真实目标控制器。
@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 链接起来。