从Storyboard实例化View Controller与创build新实例
从故事板实例化视图控制器和创build它的新实例之间的function区别是什么? 例如:
#import "SomeViewController.h" ... SomeViewController *someViewController = [SomeViewController new];
与
#import "SomeViewController.h" ... UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil]; SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];
在任何情况下, someViewController
有效地是相同的东西?
主要区别在于你的UIViewController
的子视图是如何实例化的。
在第二种情况下,您在故事板中创build的所有视图都将自动为您实例化,所有sockets和动作将按照您在故事板中指定的方式进行设置。
在第一种情况下,没有一件事情发生。 你只是得到原始对象。 您需要分配和实例化所有子视图,使用约束或其他方式将其展开,并自行连接所有的sockets和操作。 苹果build议通过覆盖UIViewController
的loadView
方法来做到这一点。
在第二种情况下,视图控制器将从故事板加载它的视图,并且您会很高兴。
在第一种情况下,它不会。 除非你已经采取了其他的步骤(比如重写loadView
或者viewDidLoad
或者创build一个名为SomeViewController.xib
), SomeViewController.xib
你只会得到一个空的白色视图而且很伤心。
这不是一回事。 在故事板中,您可能已经布置了一些UI元素。 他们可能会通过故事板设置约束和属性。 当您通过故事板实例化视图控制器时,您将获得有关这些子视图的位置以及它们的属性的所有说明。 如果你只是说[SomeViewController new]
你没有得到故事板对视图控制器的所有说明。
一个不错的testing是将UIViewController添加到故事板,并将红色的视图拖到它上面。 使用两种方法实例化它,看看有什么不同。
在Swift中你可以做同样的事情,
var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
您需要将Storyboard中的Identifier赋予SomeViewController,并勾选勾选Use Storyboard ID
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 } }
如果你不想使用instantiateViewControllerWithIdentifier
实例化一个新的VC,但是访问由AppDelegate中的故事板创build的实例:
- 在AppDelegate.h中创build一个属性,这样它就可以通过使用它的类来访问
@property (nonatomic, strong) myViewControllerClass*vC;
- 在myViewControllerClass.m中的
viewDidLoad
,我访问AppDelegate的共享实例,并用self提供属性:[AppDelegate sharedInstance].vC = self;
我不得不在一个复杂的故事板中使用这个解决scheme,但仍然无法克服这个事实,即我无法简单地通过解决它们的标识符来find在故事板中访问所有(或者至less我需要的)对象的简单方法。
另一件要检查的是,如果抛出错误的viewcontroller有一个storyboardIdentifier,你可以检查故事板xib文件。
在我的情况下,标识符丢失,当我添加它时,错误停止