从故事板中实例化View Controller与创建它的新实例之间的功能区别是什么?例如:
#import "SomeViewController.h"
...
SomeViewController *someViewController = [SomeViewController new];
与
#import "SomeViewController.h"
...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];
在任何一种情况下,someViewController
实际上都是一样的吗?
答案 0 :(得分:32)
主要区别在于UIViewController
的子视图如何实例化。
在第二种情况下,您在故事板中创建的所有视图都将自动为您实例化,并且所有插座和操作都将按照您在故事板中的指定进行设置。
在第一种情况下,没有一种情况发生;你只需要获得原始对象。您需要分配和实例化所有子视图,使用约束或其他方式进行布局,并自行连接所有插座和操作。 Apple recommends通过覆盖loadView
的{{1}}方法来执行此操作。
答案 1 :(得分:13)
在第二种情况下,视图控制器将从故事板加载其视图,您会很高兴。
在第一种情况下,它不会被激活。除非您已采取其他步骤(例如覆盖loadView
或viewDidLoad
或创建名为SomeViewController.xib
的xib),否则您只会获得空白视图并感到悲伤。
答案 2 :(得分:3)
这不是一回事。在故事板中,您可能已经布置了一些UI元素。他们可能通过故事板设置约束和属性。通过故事板实例化视图控制器时,您将获得有关这些子视图的位置以及它们的属性的所有说明。如果你只是说[SomeViewController new]
,你没有得到故事板对视图控制器的所有说明。
一个不错的测试是将UIViewController添加到故事板并将红色视图拖到它上面。使用两种方法对其进行实例化,看看有什么不同。
答案 3 :(得分:3)
在Swift中你也可以这样做,
var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
您需要将Storyboard中的标识符提供给SomeViewController并勾选复选标记使用Storyboard ID
答案 4 :(得分:1)
simple swift 3 extension
fileprivate enum Storyboard : String {
case main = "Main"
}
fileprivate extension UIStoryboard {
static func loadFromMain(_ identifier: String) -> UIViewController {
return load(from: .main, identifier: identifier)
}
static func load(from storyboard: Storyboard, identifier: String) -> UIViewController {
let uiStoryboard = UIStoryboard(name: storyboard.rawValue, bundle: nil)
return uiStoryboard.instantiateViewController(withIdentifier: identifier)
}
}
// MARK: App View Controllers
extension UIStoryboard {
class func loadHomeViewController() -> HomeViewController {
return loadFromMain("HomeViewController") as! HomeViewController
}
}
答案 5 :(得分:0)
如果您不想使用instantiateViewControllerWithIdentifier
实例化新VC,而是从AppDelegate访问由故事板创建的实例:
@property (nonatomic, strong) myViewControllerClass*vC;
viewDidLoad
中的[AppDelegate sharedInstance].vC = self;
我不得不在一个复杂的故事板中使用这个解决方案,仍然无法克服这样一个事实:我找不到一个简单的方法来访问所有(或至少我需要的)对象故事板简单地通过解决他们的标识符。
答案 6 :(得分:0)
要检查的另一件事是,如果引发错误的viewcontroller有一个storyboardIdentifier,你可以查看storyboard xib文件。
在我的情况下缺少标识符,当我添加它时错误停止