我已经检查了Rhubarb建议的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
视图控制器
当您想要推送在外部故事板中定义的视图控制器时,问题就开始了。这种情况下会复制属性。相反,我们可以实现一个自定义的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将视图控制器链接起来。
![IB截图](https://istack.dev59.com/UUfUc.webp)