多个故事板:我应该使用单例模式来缓存它们吗?

Multiple storyboards: should I use a singleton pattern to cache them?

我在我的应用程序中使用了多个故事板,这被认为是一种很好的做法。例如,从我在 Main.storyboard 中的 FooViewController,当点击一个按钮时,我将以编程方式跳转到 Secondary.storyboard 中定义的另一个 BarViewController

故事板和视图控制器之间的转换是在单独的文件中实现的,例如Storyboards,像下面这样:

// in Storyboards.m
@implementation Storyboards

+ (id)instantiateBarViewController {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Secondary" bundle:nil];
    return [storyboard instantiateViewControllerWithIdentifier:@"BarViewController"];
}

@end

然后在FooViewController,我这样做了:

// in FooViewController.m
- (IBAction)someButtonTapped:(id)sender {
    BarViewController *controller = [Storyboards instantiateBarViewController];
    [self.navigationController pushViewController:controller animated:YES];
}

这很好用。但我的问题是:

  1. 是否需要缓存storyboard实例,这样每次调用instantiateBarViewController时,我都不需要重新创建storyboard?
  2. 如果是,我也应该缓存 BarViewController 吗?

为了缓存故事板(和视图控制器),我可以使用如下代码:

// in Storyboards.m
@implementation Storyboards

+ (id)instantiateBarViewController {
    static UIViewController *barViewController = nil;  // Shared view controller.
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        UIStoryboard *storyboard = [self secondaryStoryboard];
        barViewController = [storyboard instantiateViewControllerWithIdentifier:@"BarViewController"];
    });
    return barViewController;
}

+ (UIStoryboard *)secondaryStoryboard {
    static UIStoryboard *storyboard = nil;  // Shared storyboard.
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        storyboard = [UIStoryboard storyboardWithName:@"Secondary" bundle:nil];
    });
    return storyboard;
}

@end

谢谢!

单例似乎有点矫枉过正 - 从情节提要中实例化视图控制器所需要做的就是:

[[UIStoryboard storyboardWithName: @"<storyboard-name>" bundle: nil] instantiateViewControllerWithIdentifier: @"<identifier>"];

[[UIStoryboard storyboardWithName: @"<storyboard-name>" bundle: nil] instantiateInitialViewController];

[self.storyboard instantiateViewControllerWithIdentifier: @"<identifier>"];

保持简单!

我会说 "don't."

像这样保持对资源的引用意味着您将东西塞进内存受限设备的内存中,并且永远不会让它们离开。 糟糕的开发者!没有饼干! ;-)

您有什么证据表明这比让系统管理缓存或丢弃重复从 xibs 加载的资源(它确实如此)更好?我会说你的方法可能弊大于利。请记住,简单地创建故事板实例并不能直接转换为 "loading it from the file system every time"。系统对此进行了相当智能的管理,因此无需通过维护永远不会释放的引用来使其短路。

如果您正在尝试解决一些性能问题,我强烈建议您使用 Instruments 来衡量性能并从那里着手。我严重怀疑这是 storyboard/xib 加载问题。