首页 文章

故事板 - 参考AppDelegate中的ViewController

提问于
浏览
119

考虑以下场景:我有一个基于故事板的应用程序 . 我将一个ViewController对象添加到storyboard中,将此ViewController的类文件添加到项目中,并在IB身份检查器中指定新类的名称 . 现在我将如何从AppDelegate以编程方式引用此ViewController?我已经使用相关类创建了一个变量并将其转换为IBOutlet属性,但我没有看到任何方法能够在代码中引用新的ViewController - 任何尝试按住Ctrl键拖动连接都不起作用 .

即在AppDelegate中我可以像这样到达基本的ViewController

(MyViewController*) self.window.rootViewController

但故事板中包含的任何其他ViewController怎么样?

3 回答

  • 165

    看看documentation-[UIStoryboard instantiateViewControllerWithIdentifier:] . 这允许您使用在IB Attributes Inspector中设置的标识符从故事板中实例化视图控制器:

    enter image description here

    已编辑以添加示例代码:

    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                             bundle: nil];
    
    MyViewController *controller = (MyViewController*)[mainStoryboard 
                        instantiateViewControllerWithIdentifier: @"<Controller ID>"];
    
  • 38

    如果你使用 XCode 5,你应该以不同的方式 .

    • UIStoryboard 中选择 UIViewController

    • 转到右上方窗格的 Identity Inspector

    • 选中 Use Storyboard ID 复选框

    • 将唯一ID写入 Storyboard ID 字段

    然后编写代码 .

    // Override point for customization after application launch.
    
    if (<your implementation>) {
        UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" 
                                                                 bundle: nil];
        YourViewController *yourController = (YourViewController *)[mainStoryboard 
          instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
        self.window.rootViewController = yourController;
    }
    
    return YES;
    
  • 8

    通常,系统应该使用故事板处理视图控制器实例化 . 您想要的是通过获取对 self.window.rootViewController 的引用来遍历viewController层次结构,而不是初始化视图控制器,如果您正确设置了故事板,则应该已经正确初始化视图控制器 .

    所以,假设你的 rootViewController 是一个UINavigationController,然后你想向它的顶级视图控制器发送一些内容,你可以在AppDelegate的_1449580中这样做:

    UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
    MyViewController *myVC = (MyViewController *)nav.topViewController;
    myVC.data = self.data;
    

    在Swift中如果非常相似:

    let nav = self.window.rootViewController as! UINavigationController;
    let myVC = nav.topViewController as! MyViewController
    myVc.data = self.data
    

    除非你想绕过故事板加载的正常方式并自己加载整个故事板,否则你真的不应该从应用程序委托中获取#1449583_ . 如果你最有可能做错了什么 . 我的意思是想象一下,出于某种原因,你希望将数据发送到视图控制器的堆栈,AppDelegate不应该是它的业务 . 它的业务是rootViewController . 让rootViewController处理自己的子节点!因此,如果我通过删除info.plist文件中对它的引用来绕过系统正常的故事板加载过程,我最多会使用 instantiateViewControllerWithIdentifier: 实例化rootViewController,如果它是容器,则可能是root用户,如UINavigationController . 您要避免的是实例化已经由故事板实例化的视图控制器 . 这是我看到的很多问题 . 简而言之,我不同意接受的答案 . 这是不正确的,除非海报意味着从info.plist删除故事板的加载,因为你将加载2个故事板,否则没有意义 . 它可能不是内存泄漏,因为系统初始化了根场景并将其分配给窗口,但随后您出现并再次实例化并再次分配它 . 你的应用程序是一个非常糟糕的开始!

相关问题