如何以编程方式从课堂加载故事板?
Posted
技术标签:
【中文标题】如何以编程方式从课堂加载故事板?【英文标题】:How can I load storyboard programmatically from class? 【发布时间】:2012-03-27 19:34:33 【问题描述】:我的问题是我正在寻找同时使用 storyboard 和 xib 的方法。但是我找不到以编程方式加载和显示故事板的正确方法。项目开始使用 xib 开发,现在很难将所有 xib 文件嵌套在情节提要中。所以我一直在寻找一种在代码中实现它的方法,比如使用 alloc, init, push
用于 viewControllers。在我的例子中,我在情节提要中只有一个控制器:UITableViewController
,它有一些我想要显示的内容的静态单元格。如果有人知道在不进行大量重构的情况下使用 xib 和故事板的正确方法,我将不胜感激。
【问题讨论】:
【参考方案1】:在您的故事板中,转到属性检查器并设置视图控制器的标识符。然后,您可以使用以下代码呈现该视图控制器。
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
【讨论】:
如果您想从场景的默认视图控制器开始,[sb instantiateInitialViewController]
很方便。
詹姆斯,谢谢!我一直在寻找相当长的时间来试图弄清楚如何实例化 Storyboard 的视图。您的答案(和 kokoko 的问题)令人耳目一新。
在 James Beith 的代码中,如果 UIViewControler *vc 与当前视图控制器来回切换,则必须重用它。我发现 vc 一直存在并连接到情节提要笔尖的困难方式,直到用户按下新视图上的按钮,现在该代码的先前咒语中丢弃的 vc 存在内存泄漏。跨度>
如果有人想知道如何在应用程序委托中执行此操作,请按以下顺序将 [self presentViewcontroller]
逻辑替换为这些行:1) self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
2) self.window.rootViewController = vc;
和 3 )[self.window makeKeyAndVisible];
。您也可以去掉 modalTransitionStyle
行,因为这不是来自应用委托的模态转换。
仅供参考,如果您想“推动”新故事板而不是模态弹出,请查看 chaithraVeeresh 的答案。【参考方案2】:
斯威夫特 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。
IB > 显示身份检查器 > 身份 > 故事板 ID
Swift(旧版)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController") as? UIViewController
self.navigationController!.pushViewController(vc!, animated: true)
编辑:Fred A. 的评论中建议使用 Swift 2
如果你想在没有任何 navigationController 的情况下使用,你必须使用如下:
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
present(vc , animated: true , completion: nil)
【讨论】:
在 Swift 2 中,不需要添加“as?UIViewController”,编译器会自动判断 或者你可以做self.storyboard
并合并line1&2【参考方案3】:
在属性检查器中给出该视图控制器的标识符,下面的代码适用于我
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
DetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
[self.navigationController pushViewController:detailViewController animated:YES];
【讨论】:
【参考方案4】:试试这个
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:@"Login"];
[[UIApplication sharedApplication].keyWindow setRootViewController:vc];
【讨论】:
如果您不使用 UINavigationController,请使用此选项,如其他答案所示【参考方案5】:在 swiftNavigationController 和 pushController 中您可以替换为
present(vc, animated:true , completion: nil)
【讨论】:
【参考方案6】:你总是可以直接跳转到根控制器:
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
【讨论】:
【参考方案7】:下面的扩展将允许您加载Storyboard
,它与UIViewController
相关联。示例:如果您有一个名为 ModalAlertViewController
的 UIViewController
和一个名为“ModalAlert”的故事板,例如
let vc: ModalAlertViewController = UIViewController.loadStoryboard("ModalAlert")
将同时加载Storyboard
和UIViewController
,vc
的类型为ModalAlertViewController
。 注意假设storyboard的Storyboard ID与storyboard同名,并且storyboard已经被标记为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
【讨论】:
【参考方案8】:对于 swift 4 和 5,您可以这样做。好的做法是将 Storyboard 的名称设置为 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)
然后您可以像这样在 ViewController 中加载 Storyboard:
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 名称
【讨论】:
以上是关于如何以编程方式从课堂加载故事板?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式将 UIImageView 添加到 UIStackView(故事板)