web-dev-qa-db-fra.com

Définir par programme le contrôleur de vue initial à l'aide de Storyboards

Comment définir par programme la InitialViewController pour un storyboard? Je souhaite ouvrir mon story-board à une autre vue en fonction de conditions pouvant varier d'un lancement à l'autre.

242
UserDev

Comment sans un contrôleur de vue initial factice

Assurez-vous que tous les contrôleurs de vue initiaux ont un ID Storyboard.

Dans le storyboard, décochez l'attribut "Est le contrôleur de vue initial" dans le premier contrôleur de vue.

Si vous exécutez votre application à ce stade, vous lirez:

Failed to instantiate the default view controller for UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry point is not set?

Et vous remarquerez que votre propriété de fenêtre dans le délégué de l'application est maintenant nulle.

Dans les paramètres de l'application, accédez à votre cible et à l'onglet Info. Là effacez la valeur de Main storyboard file base name. Dans l'onglet General, effacez la valeur pour Main Interface. Cela supprimera l'avertissement.

Créez la fenêtre et le contrôleur de vue initial souhaité dans la méthode application:didFinishLaunchingWithOptions: du délégué de l'application:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];

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

    UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];

    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];

    return YES;
}
455
Travis

Pour tous les amoureux Swift , voici la réponse de @ Travis traduit en Swift :

Faites ce que @ Travis a expliqué avant le code Objective C. Ensuite,

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var exampleViewController: ExampleViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ExampleController") as! ExampleViewController

    self.window?.rootViewController = exampleViewController

    self.window?.makeKeyAndVisible()

    return true
}

La ExampleViewController serait le nouveau contrôleur de vue initial que vous souhaitez afficher.

Les étapes expliquées:

  1. Créer une nouvelle fenêtre avec la taille de la fenêtre actuelle et la définir comme notre fenêtre principale
  2. Instanciez un storyboard que nous pouvons utiliser pour créer notre nouveau contrôleur de vue initial
  3. Instanciez notre nouveau contrôleur de vue initial en fonction de son ID Storyboard
  4. Définissez le contrôleur de vue racine de notre nouvelle fenêtre comme notre nouveau contrôleur que nous venons d'initier
  5. Rendre notre nouvelle fenêtre visible

Bonne et joyeuse programmation!

116
Display name

Vous pouvez définir par programme le rootViewController de la fenêtre de clé dans (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

par exemple:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (shouldShowAnotherViewControllerAsRoot) {
        UIStoryboard *storyboard = self.window.rootViewController.storyboard;
        UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"rootNavigationController"];
        self.window.rootViewController = rootViewController;
        [self.window makeKeyAndVisible];
    }

    return YES;
}
45
Chengjiong

Swift 3: Mise à jour vers le code de @ victor-sigler

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)

    // Assuming your storyboard is named "Main"
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

    // Add code here (e.g. if/else) to determine which view controller class (chooseViewControllerA or chooseViewControllerB) and storyboard ID (chooseStoryboardA or chooseStoryboardB) to send the user to

    if(condition){
        let initialViewController: chooseViewControllerA = mainStoryboard.instantiateViewController(withIdentifier: "chooseStoryboardA") as! chooseViewControllerA
        self.window?.rootViewController = initialViewController
    )
    }else{
        let initialViewController: chooseViewControllerB = mainStoryboard.instantiateViewController(withIdentifier: "chooseStoryboardB") as! chooseViewControllerB
        self.window?.rootViewController = initialViewController
    )

    self.window?.makeKeyAndVisible(

    return true
}
13
MEK

Vous pouvez définir navigation rootviewcontroller en tant que contrôleur de vue principale. Cette idée peut être utilisée pour la connexion automatique conformément aux exigences de l'application.

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

UIViewController viewController = (HomeController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"HomeController"];

UINavigationController navController = [[UINavigationController alloc] initWithRootViewController:viewController];

 self.window.rootViewController = navController;

if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {

    // do stuff for iOS 7 and newer

    navController.navigationBar.barTintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];

    navController.navigationItem.leftBarButtonItem.tintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];

    navController.navigationBar.tintColor = [UIColor whiteColor];

    navController.navigationItem.titleView.tintColor = [UIColor whiteColor];

    NSDictionary *titleAttributes =@{

                                     NSFontAttributeName :[UIFont fontWithName:@"Helvetica-Bold" size:14.0],

                                     NSForegroundColorAttributeName : [UIColor whiteColor]

                                     };

    navController.navigationBar.titleTextAttributes = titleAttributes;

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

}

else {

    // do stuff for older versions than iOS 7

    navController.navigationBar.tintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];



    navController.navigationItem.titleView.tintColor = [UIColor whiteColor];

}

[self.window makeKeyAndVisible];

Pour les utilisateurs de StoryboardSegue

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

// Go to Login Screen of story board with Identifier name : LoginViewController_Identifier

LoginViewController *loginViewController = (LoginViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:@“LoginViewController_Identifier”];

navigationController = [[UINavigationController alloc] initWithRootViewController:testViewController];

self.window.rootViewController = navigationController;

[self.window makeKeyAndVisible];

// Go To Main screen if you are already Logged In Just check your saving credential here

if([SavedpreferenceForLogin] > 0){
    [loginViewController performSegueWithIdentifier:@"mainview_action" sender:nil];
}

Merci

9
Bhavsar1311

Ouvrez mainstoryboard, sélectionnez la vue que vous souhaitez commencer, puis ouvrez Utilitaires -> Attributs. Sous le "View Controller", vous voyez le bouton radio "Is initial View Controller". Il suffit de le sélectionner.

--- À la question révisée:

Peut-être que vous pouvez essayer ceci: écrivez une méthode dans la section ViewDidLoad de votre vue initiale et lorsque la méthode s’exécute au lancement de l’application, cette méthode déclenche le passage à une autre vue.

6
m.etka

Dans AppDelegate.Swift, vous pouvez ajouter le code suivant:

let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "YourViewController_StorboardID")
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()

Bien entendu, vous devez implémenter votre logique en fonction des critères sur lesquels vous choisirez un contrôleur de vue approprié.

N'oubliez pas non plus d'ajouter une identité (sélectionnez le scénario -> Scène du contrôleur -> Afficher l'inspecteur d'identité -> attribuez StorboardID).

2
Nedim Talovic

Je ne pense pas que ce soit possible. Au lieu de cela, vous pouvez avoir un seul contrôleur initial, qui se divise en différents contrôleurs de vue. Au démarrage, vous pouvez choisir la séquence à exécuter par programme.

2
Shmidt

Une autre solution avec utiliser Swift et Swift 4 en évitant le lancement forcé est comme ceci

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewController") as? YourViewController else {
        return false
    }
    self.window?.rootViewController = viewController
    self.window?.makeKeyAndVisible()
    return true
}

Et ci-dessous utilise avec UINavigationController

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewController") as? YourViewController else {
        return false
    }
    let navigationController = UINavigationController(rootViewController: viewController)
    self.window?.rootViewController = navigationController
    self.window?.makeKeyAndVisible()
    return true
}
2
abdullahselek

Vous pouvez définir initial view controller à l'aide d'Interface Builder et par programme.

Vous trouverez ci-dessous une approche utilisée par programmation.

Objective-C:

        self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

        UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"HomeViewController"]; // <storyboard id>

        self.window.rootViewController = viewController;
        [self.window makeKeyAndVisible];

        return YES;

Swift:

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

        var objMainViewController: MainViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MainController") as! MainViewController

        self.window?.rootViewController = objMainViewController

        self.window?.makeKeyAndVisible()

        return true
2
Jayprakash Dubey

J'ai créé une classe de routage pour gérer la navigation dynamique et garder la classe AppDelegate propre. J'espère que cela aidera également les autres.

//
//  Routing.Swift
// 
//
//  Created by Varun Naharia on 02/02/17.
//  Copyright © 2017 TechNaharia. All rights reserved.
//

import Foundation
import UIKit
import CoreLocation

class Routing {

    class func decideInitialViewController(window:UIWindow){
        let userDefaults = UserDefaults.standard
        if((Routing.getUserDefault("isFirstRun")) == nil)
        {
            Routing.setAnimatedAsInitialViewContoller(window: window)
        }
        else if((userDefaults.object(forKey: "User")) != nil)
        {
            Routing.setHomeAsInitialViewContoller(window: window)
        }
        else
        {
            Routing.setLoginAsInitialViewContoller(window: window)
        }

    }

    class func setAnimatedAsInitialViewContoller(window:UIWindow) {
        Routing.setUserDefault("Yes", KeyToSave: "isFirstRun")
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let animatedViewController: AnimatedViewController = mainStoryboard.instantiateViewController(withIdentifier: "AnimatedViewController") as! AnimatedViewController

        window.rootViewController = animatedViewController
        window.makeKeyAndVisible()
    }

    class func setHomeAsInitialViewContoller(window:UIWindow) {
        let userDefaults = UserDefaults.standard
        let decoded  = userDefaults.object(forKey: "User") as! Data
        User.currentUser = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! User

        if(User.currentUser.userId != nil && User.currentUser.userId != "")
        {
            let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let homeViewController: HomeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
            let loginViewController: UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "LoginNavigationViewController") as! UINavigationController
            loginViewController.viewControllers.append(homeViewController)
            window.rootViewController = loginViewController
        }
        window.makeKeyAndVisible()
    }

    class func setLoginAsInitialViewContoller(window:UIWindow) {
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let loginViewController: UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "LoginNavigationViewController") as! UINavigationController

        window.rootViewController = loginViewController
        window.makeKeyAndVisible()
    }

  class func setUserDefault(_ ObjectToSave : Any?  , KeyToSave : String)
    {
        let defaults = UserDefaults.standard

        if (ObjectToSave != nil)
        {

            defaults.set(ObjectToSave, forKey: KeyToSave)
        }

        UserDefaults.standard.synchronize()
    }

    class func getUserDefault(_ KeyToReturnValye : String) -> Any?
    {
        let defaults = UserDefaults.standard

        if let name = defaults.value(forKey: KeyToReturnValye)
        {
            return name as Any
        }
        return nil
    }

    class func removetUserDefault(_ KeyToRemove : String)
    {
        let defaults = UserDefaults.standard
        defaults.removeObject(forKey: KeyToRemove)
        UserDefaults.standard.synchronize()
    }

}

Et dans votre AppDelegate appelez ça

 self.window = UIWindow(frame: UIScreen.main.bounds)
 Routing.decideInitialViewController(window: self.window!)
2
Varun Naharia

Merci modifié ceci comme suit dans AppDelegate:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) ->     Bool {
//Some code to check value of pins

if pins! == "Verified"{
        print(pins)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "HomePage", bundle: nil)
        let exampleViewController: UINavigationController = mainStoryboard.instantiateViewControllerWithIdentifier("SBHP") as! UINavigationController

        self.window?.rootViewController = exampleViewController

        self.window?.makeKeyAndVisible()
    }else{
        print(pins)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let exampleViewController: UINavigationController = mainStoryboard.instantiateViewControllerWithIdentifier("SBUser") as! UINavigationController

        self.window?.rootViewController = exampleViewController

        self.window?.makeKeyAndVisible()
    }
0
Jeremy

Solution simple trouvée - inutile de supprimer "la vérification initiale du contrôleur de la vue" de l'onglet Infos du projet de montage et d'édition et d'utiliser makeKeyAndVisible, il suffit de placer

self.window.rootViewController = rootVC;

dans

- (BOOL) application:didFinishLaunchingWithOptions:
0
alex1704
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewController(withIdentifier: "storyBoardid") as! ViewController
let navigationController = UINavigationController(rootViewController: vc)
UIApplication.shared.delegate.window?.rootViewController = navigationController

Une autre façon est de présenter viewController,

let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewController(withIdentifier: "storyBoardid") as! ViewController
self.present(vc,animated:true,completion:nil)

Vous devez d’abord créer un objet de votre storyboard, puis changer de racine (si nécessaire), puis prendre référence au contrôleur de vue particulier sur lequel le contrôleur de vue actuel est poussé (si vous changez de racine), sinon c’est simplement le nouveau contrôleur de vue

0
V D Purohit
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        if (PreferenceHelper.getAccessToken() != "") {
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "your View Controller Identifier")
            self.window?.rootViewController = initialViewController
        } else {
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "your View Controller identifier")
            self.window?.rootViewController = initialViewController
        }
        self.window?.makeKeyAndVisible()
        return true
    }

/*
use your view Controller identifier must use it doubles quotes**strong text**
0
charles

Il y a quelques jours, j'ai rencontré la même situation. Une astuce très simple a résolu ce problème. J'ai caché mon contrôleur de vue initial avant launch2. Si le contrôleur de vue initial est le bon contrôleur, il est défini sur visible dans viewDidLoad. Sinon, une séquence est effectuée sur le contrôleur de vue souhaité. Cela fonctionne parfaitement dans iOS 6.1 et supérieur. Je suis sûr que cela fonctionne sur les versions antérieures d'iOS.

0
m.etka

Swift 4, Xcode 9

dans le fichier AppDelegate.Swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let firstVC = storyboard.instantiateViewController(withIdentifier: "firstViewController") as! firstViewController
    self.window?.rootViewController = firstVC
}
0
Shan Ye