在 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
返回AnyObject
(id
在 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的主要内容,如果未能解决你的问题,请参考以下文章
为什么匿名内部类可以实例化并实现抽象方法?lambda表达式是简化了匿名内部类的实现过程吗?