如何从课堂上以编程方式加载情节提要?


183

我的问题是我正在寻找同时使用情节提要xib的方法。但是我找不到以编程方式加载和显示情节提要的正确方法。该项目是从xib开始开发的,现在很难将所有xib文件嵌套在情节提要中。所以我一直在寻找一种在代码中实现它的方法,就像使用alloc, init, pushviewControllers一样。就我而言,情节提要中只有一个控制器:UITableViewController,它具有静态单元格,其中包含一些我想显示的内容。如果有人知道在不进行大量重构的情况下使用xib和Storyboard的正确方法,我将不胜感激。

Answers:


370

在情节提要中,转到“属性”检查器,然后设置视图控制器的“标识符”。然后,您可以使用以下代码显示该视图控制器。

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];

65
[sb instantiateInitialViewController]如果要在场景的默认视图控制器上启动,则非常方便。
提请2012年

詹姆斯,谢谢!我一直在寻找相当长的时间,试图弄清楚如何实例化情节提要的视图。您的答案(以及kokoko的问题)最令人耳目一新。
bejonbee 2012年

根据James Beith的代码,如果要与当前的viewcontroller来回切换,则必须重用该UIViewControler * vc。我发现了vc粘住并连接到情节提要笔尖的困难方式,直到用户按下新视图上的按钮为止,现在存在内存泄漏,该代码的先前实例中丢弃了vc。
SWoo,2014年

11
如果有人想知道如何在应用程序委托中执行此操作,请[self presentViewcontroller]按以下顺序用以下几行替换逻辑:1)self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];2)self.window.rootViewController = vc;和3)[self.window makeKeyAndVisible];。您也可以摆脱这一限制,modalTransitionStyle因为这不是来自应用程序委托的模式转换。
lewiguez 2014年

仅供参考,如果您要“推送”新的故事板,而不是突然弹出,请查看chaithraVeeresh的回答。
亚当·约翰斯

76

迅捷3

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "viewController")
self.navigationController!.pushViewController(vc, animated: true)

迅捷2

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController")
self.navigationController!.pushViewController(vc, animated: true)

先决条件

为您的视图控制器分配一个Storyboard ID

情节提要ID

IB>显示身份检查器>身份>故事板ID

斯威夫特(旧版)

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController") as? UIViewController
self.navigationController!.pushViewController(vc!, animated: true)

编辑:斯威夫特2在弗雷德·A的评论中建议

如果您想在没有任何navigationController的情况下使用,则必须使用以下代码:

    let Storyboard  = UIStoryboard(name: "Main", bundle: nil)
    let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
    present(vc , animated: true , completion: nil)

1
在斯威夫特2,你不需要加上“的UIViewController?”时,编译器会自动确定它
弗雷德里克·阿达

2
或者您可以self.storyboard合并并合并line1&2
Honey

17

在属性检查器中,为该视图控制器提供标识符,以下代码对我有用

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
DetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
[self.navigationController pushViewController:detailViewController animated:YES];

5

试试这个

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:@"Login"];

[[UIApplication sharedApplication].keyWindow setRootViewController:vc];

如果您未如其他答案所示使用UINavigationController,请使用此选项
latenitecoder

2

在swift
NavigationControllerpushController中,您可以替换为

present(vc, animated:true , completion: nil)

1

对于3和4,可以执行此操作。优良作法是将故事板的名称设置为等于StoryboardID。

enum StoryBoardName{
   case second = "SecondViewController"
}
extension UIStoryBoard{
   class func load(_ storyboard: StoryBoardName) -> UIViewController{
      return UIStoryboard(name: storyboard.rawValue, bundle: nil).instantiateViewController(withIdentifier: storyboard.rawValue)
   }
}

然后您可以像这样将Storyboard加载到ViewController中:

class MyViewController: UIViewController{
     override func viewDidLoad() {
        super.viewDidLoad()
        guard let vc = UIStoryboard.load(.second) as? SecondViewController else {return}
        self.present(vc, animated: true, completion: nil)
     }

}

创建新的Storyboard时,只需在StoryboardID上设置相同的名称,然后在枚举“ StoryBoardName ”中添加Storyboard名称。


0

您总是可以直接跳到根控制器:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];

0

以下扩展名将允许您加载Storyboard和关联的UIViewController。示例:如果您有一个UIViewController名为ModalAlertViewController和名为“ ModalAlert”的情节提要,例如

let vc: ModalAlertViewController = UIViewController.loadStoryboard("ModalAlert")

将同时加载StoryboardUIViewControllervc将为类型ModalAlertViewController注意假定情节提要的情节提要ID与情节提要具有相同的名称,并且该情节提要被标记为Is Initial View Controller

extension UIViewController {
    /// Loads a `UIViewController` of type `T` with storyboard. Assumes that the storyboards Storyboard ID has the same name as the storyboard and that the storyboard has been marked as Is Initial View Controller.
    /// - Parameter storyboardName: Name of the storyboard without .xib/nib suffix.
    static func loadStoryboard<T: UIViewController>(_ storyboardName: String) -> T? {
        let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
        if let vc = storyboard.instantiateViewController(withIdentifier: storyboardName) as? T {
            vc.loadViewIfNeeded() // ensures vc.view is loaded before returning
            return vc
        }
        return nil
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.