在 Swift 中实例化并呈现视图控制器

问题描述 投票:0回答:18

问题

我开始查看

Swift Programming Language
,不知怎的,我无法从特定的
UIViewController
正确输入
UIStoryboard
的初始化。

Objective-C
中我简单地写:

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

任何人都可以帮助我如何在 Swift 上实现这一目标吗?

ios objective-c swift uiviewcontroller
18个回答
745
投票

此答案最后针对 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


45
投票
对于使用

@akashivskyy 的答案 来实例化 UIViewController

 并有例外的人:

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

快速提示:

在您尝试实例化的目的地

required init?(coder aDecoder: NSCoder)

 手动实现 
UIViewController


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

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

这里


20
投票

此链接有两种实现:

斯威夫特:

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"];

此链接包含用于在同一故事板中启动视图控制器的代码

/* 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) }
    

15
投票
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];
    

14
投票
Swift 4.2更新的代码是

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

7
投票
// "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)
    

7
投票
我想建议一种更干净的方法。当我们有多个故事板时这将很有用

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
    

5
投票
无论我尝试什么,它对我来说都不起作用 - 没有错误,但我的屏幕上也没有新的视图控制器。不知道为什么,但将其包装在超时函数中最终使其工作:

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) }
    

3
投票
斯威夫特3

Storyboard

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

3
投票
斯威夫特 4:

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

2
投票
如果你有一个不使用任何storyboard/Xib的Viewcontroller,你可以像下面的调用一样推送到这个特定的VC:

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

2
投票
斯威夫特5

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

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

我创建了一个构建时脚本(您

可以在此处访问),它将创建一个编译器安全的方法,用于从给定项目中的所有故事板访问和实例化视图控制器。

例如,

Main.storyboard中名为vc1的视图控制器将像这样实例化:

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

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

https://github.com/Jasperav/Storyboardable

只需更改 Storyboard.swift 并让

ViewControllers

 符合 
Storyboardable


0
投票
guard let vc = storyboard?.instantiateViewController(withIdentifier: "add") else { return } vc.modalPresentationStyle = .fullScreen present(vc, animated: true, completion: nil)
    

0
投票
我使用这个助手:

struct Storyboard<T: UIViewController> { static var storyboardName: String { return String(describing: T.self) } static var viewController: T { let storyboard = UIStoryboard(name: "Main", bundle: nil) guard let vc = storyboard.instantiateViewController(withIdentifier: Self.storyboardName) as? T else { fatalError("Could not get controller from Storyboard: \(Self.storyboardName)") } return vc } }
使用(Storyboard ID 必须与 UIViewController 类名匹配)

let myVC = Storyboard.viewController as MyViewController
    

0
投票
if let destinationVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DestinationVC") as? DestinationVC { let nav = self.navigationController //presenting nav?.present(destinationVC, animated: true, completion: { }) //push nav?.pushViewController(destinationVC, animated: true) }
    
© www.soinside.com 2019 - 2024. All rights reserved.