Comment créer un nouveau projet Swift sans utiliser de storyboards?

107

La création d'un nouveau projet dans XCode 6 ne permet pas de désactiver les storyboards. Vous pouvez uniquement sélectionner Swift ou Objective-C et utiliser ou non les Core Data.

J'ai essayé de supprimer le storyboard et du projet en supprimant le storyboard principal et en définissant manuellement la fenêtre de didFinishLaunching

Dans l'AppDelegate, j'ai ceci:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow
var testNavigationController: UINavigationController

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

        testNavigationController = UINavigationController()
        var testViewController: UIViewController = UIViewController()
        self.testNavigationController.pushViewController(testViewController, animated: false)

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

        self.window.rootViewController = testNavigationController

        self.window.backgroundColor = UIColor.whiteColor()

        self.window.makeKeyAndVisible()

        return true
    }
}

Cependant, XCode me donne une erreur:

La classe 'AppDelegate' n'a aucun initialiseur

Quelqu'un y a-t-il réussi?

EhTd
la source
1
Reproduction possible de Comment créer une application vide dans Xcode 6 sans Storyboard
S1LENT WARRIOR

Réponses:

71

Vous devez marquer les variables windowet testNavigationControllercomme facultatives:

var window : UIWindow?
var testNavigationController : UINavigationController?

Les classes Swift nécessitent l'initialisation des propriétés non facultatives lors de l'instanciation:

Les classes et les structures doivent définir toutes leurs propriétés stockées sur une valeur initiale appropriée au moment où une instance de cette classe ou structure est créée. Les propriétés stockées ne peuvent pas être laissées dans un état indéterminé.

Les propriétés de type facultatif sont automatiquement initialisées avec une valeur de nil, indiquant que la propriété est délibérément destinée à n'avoir «pas encore de valeur» lors de l'initialisation.

Lorsque vous utilisez des variables facultatives, n'oubliez pas de les déballer avec !, par exemple:

self.window!.backgroundColor = UIColor.whiteColor();
akashivskyy
la source
1
Tout est parfaitement logique dans votre réponse, jusqu'à la fin. pouvez-vous expliquer cette dernière partie? déballer? est-ce nécessaire?
DanMoore
1
Vous ne pouvez pas stocker une propriété non facultative dans votre AppDelegate(sauf si elle a une valeur lors de l'initialisation, ou si elle est résolue paresseusement). Si vous stockez une propriété facultative et que vous êtes sûr que ce n'est pas le cas nil, vous la «retirez de son option» à l'aide de l' !opérateur.
akashivskyy
quelle est la meilleure pratique, self.window! ou en utilisant if let window = ..?
rire
1
Si vous êtes sûr que votre fenêtre existe (et que vous pouvez être sûr dans ce cas particulier), vous pouvez y aller !.
akashivskyy
cela signifie-t-il que lorsque nous utilisons des storyboards, le backgroundColor est-il par défaut .white?
Honey
91

Tout ce qu'il faut pour ne pas utiliser les Storyboards pour rootViewController:

1 · Remplacer AppDelegate.swiftpar:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        if let window = window {
            window.backgroundColor = UIColor.white
            window.rootViewController = ViewController()
            window.makeKeyAndVisible()
        }
        return true
    }
}

2 · Créez une ViewControllersous - classe de UIViewController:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.blue
    }
}

3 · Si vous avez créé le projet à partir d'un modèle Xcode:

  1. Supprimez la paire clé-valeur pour la clé "Main storyboard file base name"de Info.plist.
  2. Supprimez le fichier de storyboard Main.storyboard.

Comme vous pouvez le voir dans le premier extrait de code, au lieu de déballer implicitement un optionnel, j'aime plutôt la if letsyntaxe pour dérouler la windowpropriété optionnelle . Ici, je l'utilise if let a = a { }pour que l'option facultative adevienne une référence non facultative à l'intérieur de la ifdéclaration avec le même nom - a.

Enfin self.n'est pas nécessaire lors du référencement de la windowpropriété dans sa propre classe.

tobiasdm
la source
1
Pourquoi le if let window = window {? Je l'ai compris! C'est pour que vous n'ayez pas besoin de l'utiliser à window!chaque fois.
Bilal Akil
@ 2unco Je suis content que vous l'ayez compris. Ceci est décrit dans la dernière partie de ma réponse sur if let a = a {}.
tobiasdm
Je déplacerais l'appel makeKeyAndVisible()à être après le réglage rootViewController. Sinon, vous recevrez un avertissement sur la façon dont la fenêtre devrait avoir un contrôleur de vue racine à la fin du lancement de l'application.
Sebastien Martin
if let a = a { }semble étrange. Êtes-vous sûr que vous pouvez utiliser le même nom de variable pour la référence non facultative? Apple utilise toujours des noms différents dans ses documents Swift. Aussi, pourquoi est-ce mieux que de simplement utiliser à window!chaque fois?
ma11hew28
1. if let a = a { }est parfaitement bien. Vous pouvez l'utiliser if let anA = a { }si cela vous met plus à l'aise. 2. window!est une vérification d'exécution puisque vous avez explicitement déballé un fichier facultatif. J'aime les vérifications de temps de compilation que Swift nous fournit, alors pourquoi ne pas l'utiliser.
tobiasdm
13

Si vous souhaitez initialiser votre viewController avec xib et que vous devez utiliser le contrôleur de navigation. Voici un morceau de code.

var window: UIWindow?
var navController:UINavigationController?
var viewController:ViewController?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    window = UIWindow(frame: UIScreen.mainScreen().bounds)

    viewController = ViewController(nibName: "ViewController", bundle: nil);
    navController = UINavigationController(rootViewController: viewController!);

    window?.rootViewController = navController;
    window?.makeKeyAndVisible()

    return true
}
Warewolf
la source
6

Essayez le code suivant:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window!.backgroundColor = UIColor.whiteColor()

    // Create a nav/vc pair using the custom ViewController class

    let nav = UINavigationController()
    let vc = NextViewController ( nibName:"NextViewController", bundle: nil)

    // Push the vc onto the nav
    nav.pushViewController(vc, animated: false)

    // Set the window’s root view controller
    self.window!.rootViewController = nav

    // Present the window
    self.window!.makeKeyAndVisible()
    return true

}
PREMKUMAR
la source
2

J'ai trouvé la réponse que cela n'avait rien à voir avec la configuration de xcode, supprimer le storyboard et la référence du projet est la bonne chose. Cela avait à voir avec la syntaxe rapide.

Le code est le suivant:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
var testNavigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

        self.testNavigationController = UINavigationController()
        var testViewController: UIViewController? = UIViewController()
        testViewController!.view.backgroundColor = UIColor.redColor()
        self.testNavigationController!.pushViewController(testViewController, animated: false)

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

        self.window!.rootViewController = testNavigationController

        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()

        return true
    }

}
EhTd
la source
Mais pourquoi répondre à votre propre question, si la solution est dans une autre réponse?
akashivskyy
la page n'a pas été mise à jour et je n'ai pas vu la réponse, seulement après la publication
EhTd
2

Vous pouvez simplement le faire comme ceci:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var IndexNavigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        var IndexViewContoller : IndexViewController? = IndexViewController()
        self.IndexNavigationController = UINavigationController(rootViewController:IndexViewContoller)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.rootViewController = self.IndexNavigationController
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        return true
    }
}
Hilen
la source
Est-ce que var window: UIWindow? spécifier que c'est une propriété facultative?
Sean Dunford
Eh bien, j'ai juste essayé d'ajouter une deuxième var dans le délégué d'application sans cela et j'ai trouvé que ma déclaration ci-dessus était vraie.
Sean Dunford
2

Je vous recommande d'utiliser le contrôleur et xib

MyViewController.swift et MyViewController.xib

(Vous pouvez créer via File-> New-> File-> Cocoa Touch Class et définir "également créer un fichier XIB" true, sous-classe de UIViewController)

class MyViewController: UIViewController {
   .....    
}

et En AppDelegate.swift func applicationécrivez le code suivant

....
var controller: MyViewController = MyViewController(nibName:"MyViewController",bundle:nil)
self.window!.rootViewController = controller
return true

Ça devrait être du travail!

Yi Feng Xie
la source
J'ai essayé de la même manière que vous l'avez mentionné, mais erreur: arrêt de l'application en raison d'une exception non interceptée `` NSInternalInconsistencyException '', raison: `` Impossible de charger NIB dans le paquet:
shripad20
2

Mis à jour pour Swift 3.0:

window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
Tiago Martinho
la source
2

Mise à jour: Swift 5 et iOS 13:

  1. Créez une application à vue unique.
  2. Supprimer Main.storyboard (clic droit et supprimer).
  3. Supprimez le nom du storyboard de la configuration de scène par défaut dans le Info.plistfichier:entrez la description de l'image ici
  4. Ouvrir SceneDelegate.swiftet changer func scenede:
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 _ = (scene as? UIWindowScene) else { return }
}

à

 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).x

    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = ViewController()
        self.window = window
        window.makeKeyAndVisible()
    }
}
Jogendra Kumar
la source
1

Voici un exemple de test rapide complet pour un UINavigationController

        import UIKit
        @UIApplicationMain
        class KSZAppDelegate: UIResponder, UIApplicationDelegate {    
          var window: UIWindow?
          var testNavigationController: UINavigationController?

          func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.        
            // Working WITHOUT Storyboard
            // see http://randexdev.com/2014/07/uicollectionview/
            // see http://stackoverflow.com/questions/24046898/how-do-i-create-a-new-swift-project-without-using-storyboards
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            if let win = window {
              win.opaque = true    
            //you could create the navigation controller in the applicationDidFinishLaunching: method of your application delegate.    
              var testViewController: UIViewController = UIViewController()
              testNavigationController = UINavigationController(rootViewController: testViewController)
              win.rootViewController = testNavigationController
              win.backgroundColor = UIColor.whiteColor()
              win.makeKeyAndVisible()
// see corresponding Obj-C in https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html#//apple_ref/doc/uid/TP40011313-CH2-SW1
        //      - (void)applicationDidFinishLaunching:(UIApplication *)application {
        //    UIViewController *myViewController = [[MyViewController alloc] init];
        //    navigationController = [[UINavigationController alloc]
        //                                initWithRootViewController:myViewController];
        //    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        //    window.rootViewController = navigationController;
        //    [window makeKeyAndVisible];
            //}
            }
            return true
          }
    }
Dmitry Konovalov
la source
0

Pourquoi ne créez-vous pas simplement une application vide? le storyboard ne m'est pas créé ...

allemattio
la source
0

Nous pouvons créer une application basée sur la navigation sans storyboard dans Xcode 6 (iOS 8) comme suit:

  • Créez une application vide en sélectionnant la langue du projet comme Swift.

  • Ajoutez de nouveaux fichiers de classe tactile Cocoa avec l'interface xib. (par exemple, TestViewController)

  • Dans le swift, un seul fichier interagit avec le fichier xib, c'est-à-dire * .swift, il n'y a pas de fichiers .h et .m.

  • Nous pouvons connecter les contrôles de xib avec un fichier swift comme dans iOS 7.

Voici quelques extraits pour travailler avec les commandes et Swift

//
//  TestViewController.swift
//

import UIKit

class TestViewController: UIViewController {

    @IBOutlet var testBtn : UIButton

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    @IBAction func testActionOnBtn(sender : UIButton) {
        let cancelButtonTitle = NSLocalizedString("OK", comment: "")

        let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)

        // Create the action.
        let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel) { action in
            NSLog("The simple alert's cancel action occured.")
        }

        // Add the action.
        alertController.addAction(cancelAction)

        presentViewController(alertController, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Modifications du fichier AppDelegate.swift

//
//  AppDelegate.swift
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var navigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()

        var testController: TestViewController? = TestViewController(nibName: "TestViewController", bundle: nil)
        self.navigationController = UINavigationController(rootViewController: testController)
        self.window!.rootViewController = self.navigationController

        return true
    }

    func applicationWillResignActive(application: UIApplication) {
}

    func applicationDidEnterBackground(application: UIApplication) {
    }

    func applicationWillEnterForeground(application: UIApplication) {
    }

    func applicationDidBecomeActive(application: UIApplication) {
    }

    func applicationWillTerminate(application: UIApplication) {
    }

}

Trouvez un exemple de code et d'autres informations sur http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -travailler-avec-commandes /

Ashish Kakkad
la source
0

Dans iOS 13 et supérieur, lorsque vous créez un nouveau projet sans storyboard, utilisez les étapes ci-dessous:

  1. Créer un projet à l'aide de Xcode 11 ou supérieur

  2. Supprimer la pointe et la classe du storyboard

  3. Ajouter un nouveau fichier avec xib

  4. Besoin de définir la vue racine comme UINavigationController SceneDelegate

  5. ajoutez ci-dessous le code func scene (_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {// Utilisez cette méthode pour éventuellement configurer et attacher l'UIWindow windowà l'UIWindowScene fournie scene. // Si vous utilisez un storyboard, la windowpropriété sera automatiquement initialisée et attachée à la scène. // Ce délégué n'implique pas que la scène ou la session de connexion est nouvelle (voir à la application:configurationForConnectingSceneSessionplace). // garde let _ = (scène comme? UIWindowScene) else {retour}

    si laissez windowScene = scène comme? UIWindowScene {self.window = UIWindow (windowScene: windowScene) laissez mainController = HomeViewController () en tant que HomeViewController laissez navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController.

Shelke Yogesh
la source