Odpowiedzi:
Jak to zrobić bez fikcyjnego kontrolera widoku początkowego
Upewnij się, że wszystkie początkowe kontrolery widoku mają identyfikator Storyboard.
W scenorysie usuń zaznaczenie atrybutu „Jest początkowy kontroler widoku” z pierwszego kontrolera widoku.
Jeśli w tym momencie uruchomisz aplikację, przeczytasz:
Failed to instantiate the default view controller for UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry point is not set?
Zauważysz, że Twoja właściwość okna w delegacie aplikacji jest teraz zerowa.
W ustawieniach aplikacji przejdź do celu i Info
karty. Tam wyczyść wartość Main storyboard file base name
. Na General
karcie wyczyść wartość dla Main Interface
. Spowoduje to usunięcie ostrzeżenia.
Utwórz okno i żądany kontroler widoku początkowego w application:didFinishLaunchingWithOptions:
metodzie delegata aplikacji :
- (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;
}
didFinishLaunchingWithOptions
jest wywoływany, gdy aplikacja jest uruchamiana w nowym procesie. Jeśli przejdziesz do ekranu głównego i wrócisz do aplikacji, ta metoda nie zostanie ponownie wywołana. (O ile iOS nie zakończy się z powodu ograniczeń pamięci.) Spróbuj zatrzymać aplikację i uruchomić ją ponownie z IDE. Jeśli problem będzie się powtarzał, opublikuj problem na SO, a chętnie pomogę, przyjacielu.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds) var storyboard = UIStoryboard(name: "Main", bundle: nil) var viewController: UIViewController = // self.window!.rootViewController = viewController self.window!.makeKeyAndVisible()
Dla wszystkich miłośników Swift , oto odpowiedź @Travis przetłumaczona na SWIFT :
Zrób to, co @Travis wyjaśnił przed kodem Celu C. Następnie,
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
Będzie nowy kontroler początkowy widok chcesz pokazać.
Wyjaśnione kroki:
Miłego i szczęśliwego programowania!
Możesz programowo ustawić rootViewController okna klucza w (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
na przykład:
- (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;
}
init()
/ deinit()
, ale bez wykonywania viewDidLoad()
lub właściwej inicjalizacji IBOutlet
-s. Upewnij się, że kod jest na to gotowy.
Swift 3: Zaktualizuj kod @ 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
}
Możesz ustawić Nawigację rootviewcontroller jako główny kontroler widoku. Ten pomysł może zostać użyty do automatycznego logowania zgodnie z wymaganiami aplikacji.
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];
Dla użytkowników 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];
}
Dzięki
Otwórz tablicę główną, wybierz widok, który chcesz zacząć, a następnie otwórz Narzędzia -> Atrybuty. Pod „View Controller” zobaczysz przycisk radiowy „Is initial View Controller”. Po prostu wybierz.
--- Na zmienione pytanie:
Możesz spróbować: napisz metodę w sekcji ViewDidLoad swojego początkowego widoku, a gdy metoda uruchomi się podczas uruchamiania aplikacji, metoda wyzwoli przejście do innego widoku.
SWIFT 5
Jeśli nie masz ustawionego ViewController jako początkowego ViewController w serii ujęć, musisz zrobić 2 rzeczy:
Na koniec możesz teraz dodać swój kod w SceneDelegate:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// Make sure you set an Storyboard ID for the view controller you want to instantiate
window?.rootViewController = storyboard.instantiateViewController(withIdentifier: identifier)
window?.makeKeyAndVisible()
}
Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set
ostrzeżenie, które otrzymałem po tym, jak zdecydowałem się utworzyć początkową VC w kodzie. Ważny punkt, gdy @ rs7 mówi „usuń pole nazwy scenorysu”, oznaczają cały wiersz listy, a nie tylko zawartość samego pola.
Można ustawić initial view controller
za pomocą Konstruktora interfejsów, a także programowo.
Poniżej przedstawiono podejście zastosowane programowo.
Cel 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;
Szybki:
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
Stworzyłem klasę routingu do obsługi dynamicznej nawigacji i utrzymania klasy AppDelegate, mam nadzieję, że pomoże to również innym.
//
// 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()
}
}
A w AppDelegate nazwij to
self.window = UIWindow(frame: UIScreen.main.bounds)
Routing.decideInitialViewController(window: self.window!)
Inne rozwiązanie z użyciem Swift 3 i Swift 4 z unikaniem rzucania siłą jest takie
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
}
A poniżej używa z 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
}
W AppDelegate.swift
możesz dodać następujący kod:
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "YourViewController_StorboardID")
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
Oczywiście musisz zaimplementować swoją logikę, na podstawie których kryteriów wybierzesz odpowiedni kontroler widoku.
Nie zapomnij również dodać tożsamości (wybierz scenorys -> Scena kontrolera -> Pokaż inspektora tożsamości -> przypisz StorboardID).
ZAKTUALIZOWANA ODPOWIEDŹ na iOS 13 i delegata sceny:
upewnij się, że w pliku info.plist przejdziesz do aplikacji Scene Manifest -> Konfiguracja sceny -> Rola sesji aplikacji -> Pozycja 0 i tam również usuń odniesienie do głównej scenorysu. W przeciwnym razie pojawi się to samo ostrzeżenie o niepowodzeniu tworzenia scenariusza.
Przenieś także kod z aplikacji delegowanej do sceny metody delegowania scen (_: willConnectTo: options :), ponieważ teraz tutaj obsługiwane są zdarzenia cyklu życia.
Kilka dni temu spotkałem się z tą samą sytuacją. Bardzo prosta sztuczka rozwiązała ten problem. Przed uruchomieniem2 ustawiłem ukryty mój początkowy kontroler widoku. Jeśli kontroler widoku początkowego jest właściwym kontrolerem, ustawiony jest jako widoczny w viewDidLoad. W przeciwnym razie wykonywany jest segment do pożądanego kontrolera widoku. Działa idealnie w iOS 6.1 i nowszych. Jestem pewien, że działa na wcześniejszych wersjach iOS.
Dzięki zmodyfikował to w AppDelegate w następujący sposób:
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()
}
Znaleziono proste rozwiązanie - nie trzeba usuwać „początkowej kontroli kontrolera widoku” z serii ujęć i edycji karty Informacje o projekcie i używać makeKeyAndVisible
, wystarczy umieścić
self.window.rootViewController = rootVC;
w
- (BOOL) application:didFinishLaunchingWithOptions:
rootVC
od instantiateViewControllerWithIdentifier
, prawda?
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
Innym sposobem jest prezentacja viewController,
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewController(withIdentifier: "storyBoardid") as! ViewController
self.present(vc,animated:true,completion:nil)
Najpierw musisz utworzyć obiekt swojej serii ujęć, a następnie zmienić root (jeśli jest to wymagane), a następnie odwołać się do konkretnego kontrolera widoku, który jest wypychany bieżącego kontrolera widoku (jeśli zmienisz root), w przeciwnym razie jest to tylko nowy kontroler widoku
Swift 4, Xcode 9
w pliku 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
}
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**
Swift 5 lub nowszy # tworzy kontroler widoku trasy według tego prostego kodu. Jeśli używasz xcode 11 lub var window: UIWindow?
nowszego, najpierw zainicjuj w AppDelegate
let rootVC = mainStoryboard.instantiateViewController(withIdentifier: "YOURCONTROLLER") as! YOURCONTROLLER
navigationController.setNavigationBarHidden(true, animated: true)
UIApplication.shared.windows.first?.rootViewController = UINavigationController.init(rootViewController: rootVC)
UIApplication.shared.windows.first?.makeKeyAndVisible()
Jeśli nie chcesz zmieniać applicationDidFinish, możesz wykonać następującą sztuczkę:
Ustaw kontroler nawigacji jako początkowy kontroler widoku i przypisz mu niestandardową klasę „MyNavigationController”. Następnie możesz dostosować jego kontroler widoku głównego podczas viewDidLoad - zastąpi on kontroler widoku głównego ustawiony w twojej serii ujęć.
class MyNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
if !isLoggedIn() {
viewControllers = [R.storyboard.authentication.loginView()!]
}
}
private func isLoggedIn() -> Bool {
return false
}
}