web-dev-qa-db-fra.com

Instancier le contrôleur de vue à partir du storyboard par rapport à la création d'une nouvelle instance

Quelle est la différence fonctionnelle entre l'instanciation d'un contrôleur de vue à partir du storyboard et la création d'une nouvelle instance de celui-ci? Par exemple:

#import "SomeViewController.h"

...

SomeViewController *someViewController = [SomeViewController new];

versus

#import "SomeViewController.h"

...

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];

Dans les deux cas, someViewController est-il effectivement la même chose?

39
Benjamin Martin

La principale différence réside dans la façon dont les sous-vues de votre UIViewController sont instanciées.

Dans le second cas, toutes les vues que vous créez dans votre storyboard seront automatiquement instanciées pour vous, et toutes les sorties et actions seront configurées comme vous l'avez spécifié dans le storyboard.

Dans le premier cas, rien de tout cela ne se produit; vous obtenez juste l'objet brut. Vous devrez allouer et instancier toutes vos sous-vues, les disposer en utilisant des contraintes ou autrement, et connecter vous-même tous les points de vente et actions. Apple recommande de faire cela en remplaçant la méthode loadView de UIViewController.

32
dpassage

Dans le second cas, le contrôleur de vue chargera sa vue depuis le storyboard et vous serez content.

Dans le premier cas, ce ne sera pas le cas. À moins que vous n'ayez pris d'autres mesures (comme remplacer loadView ou viewDidLoad ou créer un xib nommé SomeViewController.xib), vous aurez juste une vue blanche vide et serez triste.

13
rob mayoff

Dans Swift vous pouvez faire de même avec,

var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController

Vous devrez donner l'identifiant dans le Storyboard au SomeViewController et cocher la coche pour Utiliser l'ID du Storyboard

3
Joseph

Ce n'est pas la même chose. Dans le storyboard, vous disposez probablement de certains éléments d'interface utilisateur. Ils peuvent avoir des contraintes et des propriétés configurées via le storyboard. Lorsque vous instanciez le viewcontroller via le storyboard, vous obtenez toutes les instructions pour savoir où se trouvent ces sous-vues et quelles sont leurs propriétés. Si vous dites simplement [SomeViewController new] vous n'obtenez pas toutes les instructions du storyboard pour le contrôleur de vue.

Un bon test consistera à ajouter un UIViewController à un storyboard et à y faire glisser une vue rouge. Instanciez-le en utilisant les deux méthodes et voyez quelles sont les différences.

3
Kris Gellci
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
        }
    }
1
Shan Shafiq

Dans le cas où vous ne souhaitez pas instancier un nouveau VC en utilisant instantiateViewControllerWithIdentifier mais en accédant à l'instance créée par le storyboard depuis AppDelegate:

  1. créer une propriété dans AppDelegate.h afin qu'elle soit accessible à partir des classes l'utilisant @property (nonatomic, strong) myViewControllerClass*vC;
  2. dans viewDidLoad à l'intérieur de myViewControllerClass.m j'accède à l'instance partagée d'AppDelegate et alimente la propriété avec self: [AppDelegate sharedInstance].vC = self;

J'ai dû utiliser cette solution dans un storyboard complexe et je n'arrive toujours pas à surmonter le fait que je ne trouve pas un moyen facile d'accéder tous (ou au moins ceux dont j'ai besoin) objets dans le storyboard simplement en adresser leurs identifiants.

0
Lookaji

une autre chose à vérifier est si le viewcontroller qui lance l'erreur a un storyboardIdentifier, vous pouvez vérifier le fichier xib du storyboard.

l'identifiant manquait dans mon cas, l'erreur s'est arrêtée quand je l'ai ajouté

0
megaKertz