从Storyboard实例化View Controller与创建新实例

时间:2014-09-30 23:12:26

标签: ios objective-c uiviewcontroller uistoryboard

从故事板中实例化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实际上都是一样的吗?

7 个答案:

答案 0 :(得分:32)

主要区别在于UIViewController的子视图如何实例化。

在第二种情况下,您在故事板中创建的所有视图都将自动为您实例化,并且所有插座和操作都将按照您在故事板中的指定进行设置。

在第一种情况下,没有一种情况发生;你只需要获得原始对象。您需要分配和实例化所有子视图,使用约束或其他方式进行布局,并自行连接所有插座和操作。 Apple recommends通过覆盖loadView的{​​{1}}方法来执行此操作。

答案 1 :(得分:13)

在第二种情况下,视图控制器将从故事板加载其视图,您会很高兴。

在第一种情况下,它不会被激活。除非您已采取其他步骤(例如覆盖loadViewviewDidLoad或创建名为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访问由故事板创建的实例:

  1. 在AppDelegate.h中创建一个属性,以便可以使用它来访问它 @property (nonatomic, strong) myViewControllerClass*vC;
  2. 在myViewControllerClass.m中的viewDidLoad中的
  3. 我访问AppDelegate的共享实例并使用self:[AppDelegate sharedInstance].vC = self;
  4. 提供该属性

    我不得不在一个复杂的故事板中使用这个解决方案,仍然无法克服这样一个事实:我找不到一个简单的方法来访问所有(或至少我需要的)对象故事板简单地通过解决他们的标识符。

答案 6 :(得分:0)

要检查的另一件事是,如果引发错误的viewcontroller有一个storyboardIdentifier,你可以查看storyboard xib文件。

在我的情况下缺少标识符,当我添加它时错误停止