Программно установить начальный вид контроллера с помощью раскадровки

216

Как программно установить InitialViewController для раскадровки? Я хочу открыть свою раскадровку для другого представления в зависимости от какого-либо состояния, которое может варьироваться от запуска до запуска.

  • 1
    Проверяйте этот ответ без предупреждения, без очистки основной раскадровки в настройках
Теги:
uiviewcontroller
uistoryboard

16 ответов

390
Лучший ответ

Как без фиктивного контроллера начального представления

Убедитесь, что все контроллеры начальных представлений имеют идентификатор раскадровки.

В раскадровке снимите флажок с атрибута "Исходный контроллер представления" с первого контроллера представления.

Если вы запустите приложение в этот момент, вы будете читать:

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

И вы заметите, что ваше свойство window в делетете приложения теперь равно нулю.

В настройках приложения перейдите к своей цели и вкладке Info. Очистите значение Main storyboard file base name. На вкладке General снимите значение для Main Interface. Это приведет к удалению предупреждения.

Создайте окно и требуемый контроллер начального представления в делетете делегата application:didFinishLaunchingWithOptions::

- (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;
}
  • 6
    Любить! Любить! Любить! Я буду использовать это для переключения между двумя совершенно разными деревьями контроллера представления для IOS6 и IOS7. Похоже, что это лучший способ справиться с обратной совместимостью, при этом все еще используются все функции IOS7.
  • 6
    Я изучаю программирование на iOS в Swift. Может кто-нибудь помочь мне, как написать приведенный выше код в Swift. пожалуйста помоги. Благодарю.
Показать ещё 16 комментариев
92

Для всех любителей Swift, вот ответ от @Travis, переведенный в SWIFT:

Сделайте то, что @Travis объясняется перед кодом Objective C. Тогда,

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
}

ExampleViewController будет новым контроллером нового представления, который вы хотели бы показать.

Действия, описанные ниже:

  • Создайте новое окно с размером текущего окна и установите его в качестве нашего главного окна.
  • Создайте раскадровку, которую мы можем использовать для создания нашего нового контроллера начального представления.
  • Создайте новый контроллер начального представления на основе его идентификатора раскадровки
  • Установите наш новый контроллер корневого представления окна как наш новый контроллер, который мы только что инициировали.
  • Сделайте наше новое окно видимым

Наслаждайтесь и наслаждайтесь программированием!

  • 0
    меня попросили @Travis за эту версию, а потом ... Спасибо, в любом случае.
  • 0
    Как создать идентификатор раскадровки в коде?
Показать ещё 2 комментария
41

Вы можете программно установить ключевое окно rootViewController в (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

например:

- (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;
}
  • 1
    Отлично написано, спасибо
  • 0
    Как затем инициировать исходную точку входа из вторичного UIViewController?
Показать ещё 5 комментариев
7

Вы можете установить навигационный контроллер rootview как основной контроллер представления. Эта идея может использоваться для автоматического входа в систему в соответствии с требованиями приложения.

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];

Для пользователей 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];
}

Спасибо

6

Swift 3: Обновление до @victor-sigler code

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
}
  • 0
    Спасибо, это работает :)
  • 0
    Спасибо, @MEK. Также вы можете исправить синтаксис операторов условного закрытия, заменив завершающие скобки фигурными скобками.
6

Откройте mainstoryboard, сначала выберите представление, которое вы хотите запустить, затем откройте "Утилиты" → "Атрибуты". Ниже "View Controller" вы видите переключатель "Is initial View Controller". Просто выберите его.

--- К пересмотренному вопросу:

Может быть, вы можете попробовать это: напишите метод в разделе ViewDidLoad вашего встроенного представления и когда метод запускается при запуске приложения, метод запускает segue в другое представление.

  • 0
    Я написал метод в ViewDidLoad, но он не работал, и когда я запишу его в viewdidAppear, он работает, вы можете объяснить, почему это происходит.
  • 0
    Возможно, вам следует попробовать это: добавить код segue в соответствии с вашими условиями к одному из соответствующих методов в файле appDelegate.m. Например, вы можете добавить код перехода в метод applicationDidBecomeActive:.
Показать ещё 3 комментария
2

Другое решение с использованием Swift 3 и Swift 4, избегая придания силы, похоже на это

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
}

И ниже используется 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

Вы можете установить initial view controller с помощью Interface Builder, а также программно.

Ниже представлен подход, используемый для программного программирования.

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

Я не думаю, что это возможно. Вместо этого у вас может быть один начальный контроллер, который будет иметь сегменты для разных контроллеров. При запуске вы можете решить, какой segue выполнять программно.

1

Я создал класс маршрутизации для динамической навигации и сохранил класс AppDelegate, я надеюсь, что это тоже поможет другим.

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

}

И в вашем AppDelegate назовите это

 self.window = UIWindow(frame: UIScreen.main.bounds)
 Routing.decideInitialViewController(window: self.window!)
0
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

Другим способом является представление viewController,

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

Сначала вам нужно создать объект своей раскадровки, а затем изменить корень (если необходимо), то вы возьмете ссылку на определенный контроллер представления, который будет нажат текущий контроллер представления (если вы измените root), иначе он просто представляет новый контроллер представлений, который может вы

  • 0
    @VD Purohit, можете ли вы подробнее рассказать о своем ответе для большего понимания?
  • 0
    Вы можете обновить описание ответа своим ответом.
0

В AppDelegate.swift вы можете добавить следующий код:

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

Конечно, вам нужно реализовать свою логику, основываясь на каких критериях вы выберете подходящий контроллер представления.

Кроме того, не забудьте добавить идентификатор.

0

Найденное простое решение - не нужно удалять "проверку контроллера начального вида" из раскадровки и редактирования вкладки "Информация о проекте" и использовать makeKeyAndVisible, просто поместите

self.window.rootViewController = rootVC;

в

- (BOOL) application:didFinishLaunchingWithOptions:
  • 0
    Но вы все еще получаете rootVC из instantiateViewControllerWithIdentifier , правильно?
  • 0
    @ Да, да, верно.
0

Спасибо, изменили это следующим образом в 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

Несколько дней назад я столкнулся с той же ситуацией. Эта простая проблема решена. Я установил скрытый свой начальный контроллер представления перед запуском2. Если начальный контроллер представления является правильным контроллером, он установлен на видимый в viewDidLoad. Кроме того, для желаемого контроллера просмотра выполняется segue. Он отлично работает в iOS 6.1 и выше. Я уверен, что он работает с более ранними версиями iOS.

-4

Выберите контроллер вида, который вы хотите открыть первым, и перейдите к инспектору атрибутов. Перейдите в исходную сцену и проверьте, есть ли опция контроля исходного вида.

Теперь это будет ваш первый контроллер представлений, который откроется первым при запуске приложения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню