在 Swift 中实例化并展示一个 viewController

Posted

技术标签:

【中文标题】在 Swift 中实例化并展示一个 viewController【英文标题】:Instantiate and Present a viewController in Swift 【发布时间】:2014-07-25 00:25:26 【问题描述】:

问题

我开始查看Swift Programming Language,但不知何故,我无法从特定UIStoryboard 正确键入UIViewController 的初始化。

Objective-C我简单写:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"StoryboardName" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"ViewControllerID"];
[self presentViewController:viewController animated:YES completion:nil];

谁能帮助我如何在 Swift 上实现这一目标?

【问题讨论】:

【参考方案1】:

此答案上次针对 Swift 5.4 和 ios 14.5 SDK 进行了修订。


这完全是新语法和稍微修改的 API 的问题。 UIKit 的底层功能没有改变。绝大多数 iOS SDK 框架都是如此。

let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myVCID")
self.present(vc, animated: true)

确保在情节提要内的“情节提要 ID”下设置 myVCID

【讨论】:

你甚至可以省略;! ;) 您介意详细说明as UIViewController 吗?为什么有必要这样做? as 关键字用于类型转换。与目标c中的(UIViewController *)anObject相同 是的,我知道我可以省略它们,但这是长期习惯的一部分。 :D 由于instantiateViewControllerWithIdentifier 返回AnyObjectid 在 Swift 中等效)并且我将vc 声明为UIViewController,我必须将AnyObject 类型转换为UIViewController 嗨朋友们,我遇到了一些不同的问题,这个代码在模拟器上运行,而不是在我的 ipad2 上运行,它有 iOS v7.1.2。如果你不介意帮我解决这个问题。 @akashivskyy 绝对是给你的。但也许对某些人来说不是。【参考方案2】:

对于使用@akashivskyy's answer 实例化UIViewController 并遇到异常的人:

致命错误:对类使用未实现的初始化程序“init(coder:)”

快速提示:

在您尝试实例化的目标UIViewController 手动实现required init?(coder aDecoder: NSCoder)

required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)

如果您需要更多描述,请参考我的回答here

【讨论】:

如果您想使用自定义启动器,您可以使用 super.init(nibName: nil, bundle: nil) 调用超级启动器,然后 whew 将加载正常或使用它们的名称调用它 NIB文件。 @user1700737 我正在实例化 viewController 引用故事板,它执行 initWithCoder,而不是 initWithNib。参考这个问题***.com/questions/24036393/… 嗨朋友们,我遇到了一些不同的问题,这个代码在模拟器上运行,而不是在我的 ipad2 上运行,它有 iOS v7.1.2。如果你不介意帮我解决这个问题。 @Indra 您需要在堆栈上提出另一个问题,给我链接我很乐意为您提供帮助! 在 Swift 1.2 上,您必须将 init(coder aDecoder: NSCoder!) 设为“必需”。所以现在你必须写以下内容:required init(coder aDecoder: NSCoder!)【参考方案3】:

This link has both the implementations:

斯威夫特:

let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)

目标 C

UIViewController *viewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"];

This link has code for initiating viewcontroller in the same storyboard

/*
 Helper to Switch the View based on StoryBoard
 @param StoryBoard ID  as String
*/
func switchToViewController(identifier: String) 
    let viewController = self.storyboard?.instantiateViewControllerWithIdentifier(identifier) as! UIViewController
    self.navigationController?.setViewControllers([viewController], animated: false)


【讨论】:

【参考方案4】:

akashivskyy 的回答很好用!但是,如果您从呈现的视图控制器返回时遇到问题,这种替代方法可能会有所帮助。它对我有用!

斯威夫特:

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController
// Alternative way to present the new view controller
self.navigationController?.showViewController(vc, sender: nil)

对象-C:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"someViewController"];
[self.navigationController showViewController:vc sender:nil];

【讨论】:

【参考方案5】:

Swift 4.2 更新代码是

let storyboard = UIStoryboard(name: "StoryboardNameHere", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerNameHere")
self.present(controller, animated: true, completion: nil)

【讨论】:

【参考方案6】:
// "Main" is name of .storybord file "
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// "MiniGameView" is the ID given to the ViewController in the interfacebuilder
// MiniGameViewController is the CLASS name of the ViewController.swift file acosiated to the ViewController
var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MiniGameView") as MiniGameViewController
var rootViewController = self.window!.rootViewController
rootViewController?.presentViewController(setViewController, animated: false, completion: nil)

当我把它放在 AppDelegate 中时,这对我来说很好

【讨论】:

【参考方案7】:

如果你想以模态方式呈现它,你应该有如下内容:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewControllerID")
self.showDetailViewController(vc as! YourViewControllerClassName, sender: self)

【讨论】:

【参考方案8】:

我想建议一种更清洁的方法。当我们有多个故事板时,这将很有用

1.使用所有故事板创建结构

struct Storyboard 
      static let main = "Main"
      static let login = "login"
      static let profile = "profile" 
      static let home = "home"
    

2。像这样创建一个 UIStoryboard 扩展

extension UIStoryboard 
  @nonobjc class var main: UIStoryboard 
    return UIStoryboard(name: Storyboard.main, bundle: nil)
  
  @nonobjc class var journey: UIStoryboard 
    return UIStoryboard(name: Storyboard.login, bundle: nil)
  
  @nonobjc class var quiz: UIStoryboard 
    return UIStoryboard(name: Storyboard.profile, bundle: nil)
  
  @nonobjc class var home: UIStoryboard 
    return UIStoryboard(name: Storyboard.home, bundle: nil)
  

给故事板标识符作为类名,并使用下面的代码来实例化

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController

【讨论】:

@nonobjc 有什么用? @StackRunner 这对目标 c 不可用【参考方案9】:

斯威夫特 3

let settingStoryboard : UIStoryboard = UIStoryboard(name: "SettingViewController", bundle: nil)
let settingVC = settingStoryboard.instantiateViewController(withIdentifier: "SettingViewController") as! SettingViewController
self.present(settingVC, animated: true, completion: 

)

【讨论】:

【参考方案10】:

无论我尝试了什么,它都对我不起作用 - 没有错误,但我的屏幕上也没有新的视图控制器。不知道为什么,但是将它包装在 timeout 函数中终于使它起作用了:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) 
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "TabletViewController")
    self.present(controller, animated: true, completion: nil)

【讨论】:

【参考方案11】:

斯威夫特 4:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let yourVC: YourVC = storyboard.instantiateViewController(withIdentifier: "YourVC") as! YourVC

【讨论】:

【参考方案12】:

如果您有一个不使用任何故事板/Xib 的 Viewcontroller,您可以推送到这个特定的 VC,如下调用:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)

【讨论】:

我明白了:“无法构造,因为它没有可访问的初始化程序”。 故事板建立的出口和其他关系丢失了【参考方案13】:

我知道这是一个旧线程,但我认为当前的解决方案(对给定的视图控制器使用硬编码的字符串标识符)很容易出错。

我创建了一个构建时脚本(您 can access here),它将创建一种编译器安全的方式,用于从给定项目中的所有情节提要访问和实例化视图控制器。

例如,Main.storyboard 中名为 vc1 的视图控制器将被实例化,如下所示:

let vc: UIViewController = R.storyboard.Main.vc1^  // where the '^' character initialize the controller

【讨论】:

【参考方案14】:

斯威夫特 5

let vc = self.storyboard!.instantiateViewController(withIdentifier: "CVIdentifier")
self.present(vc, animated: true, completion: nil)

【讨论】:

【参考方案15】:

我创建了一个库,它可以通过更好的语法更轻松地处理这个问题:

https://github.com/Jasperav/Storyboardable

只需更改 Storyboard.swift 并让 ViewControllers 符合 Storyboardable

【讨论】:

【参考方案16】:
guard let vc = storyboard?.instantiateViewController(withIdentifier: "add") else  return 
        vc.modalPresentationStyle = .fullScreen
        present(vc, animated: true, completion: nil)

【讨论】:

请为您的答案添加一些解释。解释底层逻辑比仅仅给出代码更重要。它可以帮助作者和其他读者自己解决这个问题和类似问题,同时为他们提供扩展编程技能所需知识的线索。

以上是关于在 Swift 中实例化并展示一个 viewController的主要内容,如果未能解决你的问题,请参考以下文章

栅格数据灰度化并前端转换展示

栅格数据灰度化并前端转换展示

Swift之扩展的使用和实例展示

为什么匿名内部类可以实例化并实现抽象方法?lambda表达式是简化了匿名内部类的实现过程吗?

如何为在播放模式下实例化并在 Unity 3d 中使用相机位置重新创建的对象添加视差

如何实例化并附加到指向我的对象的指针的 QVector