web-dev-qa-db-fra.com

Instancier et présenter un contrôleur de vue dans Swift

Problème

J'ai commencé à regarder la nouvelle Swift sur Xcode 6 et j'ai essayé des projets de démonstration et des tutoriels. Maintenant je suis coincé à:

Instanciation puis présentation d'une viewController à partir d'un storyboard spécifique

Solution Objective-C

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"myStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"myVCID"];
[self presentViewController:vc animated:YES completion:nil];

Comment y parvenir sur Swift?

261
EridB

Tout est une question de nouvelle syntaxe, la fonctionnalité n'a pas changé:

// Swift 3.0

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController")
self.present(controller, animated: true, completion: nil)

Si vous rencontrez des problèmes avec init(coder:), veuillez vous référer à La réponse d'EridB .

571
akashivskyy

Pour les personnes qui utilisent @ akashivskyy answer pour instancier UIViewController et qui ont l'exception:

erreur fatale: utilisation d'initialiseur non implémenté 'init (codeur :)' pour la classe

Conseil rapide:

Implémentez manuellement required init?(coder aDecoder: NSCoder) sur votre destination UIViewController que vous essayez d'instancier

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Si vous avez besoin de plus de description s'il vous plaît se référer à ma réponse ici

41
EridB

Ce lien a les deux implémentations:

Rapide:

let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)

Objectif c

UIViewController *viewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"];

Ce lien contient du code permettant d'initier viewcontroller dans le même scénario

/*
 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)

}
16
Abhijeet

la réponse d'akashivskyy fonctionne très bien! Toutefois, si vous rencontrez des difficultés pour revenir du contrôleur de vue présenté, cette alternative peut être utile. Cela a fonctionné pour moi!

Rapide:

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)

Obj-C:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"someViewController"];
[self.navigationController showViewController:vc sender:nil];
11
Nahuel Roldan
// "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)

Cela a bien fonctionné pour moi quand je l'ai mis dans AppDelegate 

7
Maxxafari

Si vous voulez le présenter de manière modale, vous devriez avoir quelque chose comme ci-dessous:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewControllerID")
self.showDetailViewController(vc as! YourViewControllerClassName, sender: self)
6
Hamid

Swift 4:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let yourVC: YourVC = storyboard.instantiateViewController(withIdentifier: "YourVC") as! YourVC
3
drew..

Swift 4.2 mis à jour le code est

let storyboard = UIStoryboard(name: "StoryboardNameHere", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerNameHere")
self.present(controller, animated: true, completion: nil)
2
Shahzaib Maqbool

Si vous avez un Viewcontroller n'utilisant pas de storyboard/Xib, vous pouvez pousser vers ce VC particulier comme ci-dessous:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)
2
Aks

Je voudrais suggérer une manière beaucoup plus propre. Cela sera utile lorsque nous avons plusieurs story-boards

1.Créez une structure avec tous vos story-boards

struct Storyboard {
      static let main = "Main"
      static let login = "login"
      static let profile = "profile" 
      static let home = "home"
    }

2. Créez une extension UIStoryboard comme celle-ci

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)
  }
}

Indiquez l'identifiant du storyboard comme nom de classe et utilisez le code ci-dessous pour instancier

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController
2
vijeesh

Swift 3 Storyboard

let settingStoryboard : UIStoryboard = UIStoryboard(name: "SettingViewController", bundle: nil)
let settingVC = settingStoryboard.instantiateViewController(withIdentifier: "SettingViewController") as! SettingViewController
self.present(settingVC, animated: true, completion: {

})
1
Giang

Peu importe ce que j'ai essayé, cela ne fonctionnerait tout simplement pas pour moi - pas d'erreur, mais pas de nouveau contrôleur de vue sur mon écran. Je ne sais pas pourquoi, mais l'envelopper dans la fonction de délai d'attente l'a finalement fait fonctionner:

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)
}
1
Starwave

Je sais que c'est un ancien fil de discussion, mais je pense que la solution actuelle (utilisant l'identifiant de chaîne codé en dur pour un contrôleur de vue donné) est très sujette aux erreurs.

J'ai créé un script de génération (auquel vous pouvez accéder ici ), qui créera un moyen sûr pour le compilateur d'accéder et d'instancier les contrôleurs de vue de tous les story-boards d'un projet donné.

Par exemple, le contrôleur de vue nommé vc1 dans Main.storyboard sera instancié de la manière suivante:

let vc: UIViewController = R.storyboard.Main.vc1^  // where the '^' character initialize the controller
1
Nadav96

J'ai créé une bibliothèque qui va gérer cela beaucoup plus facilement avec une meilleure syntaxe: 

https://github.com/Jasperav/Storyboardable

Il suffit de changer Storyboard.Swift et de laisser le ViewControllers se conformer à Storyboardable.

0
J. Doe