Come faccio a creare un nuovo progetto Swift senza usare gli storyboard?


107

La creazione di un nuovo progetto in XCode 6 non consente di disabilitare gli storyboard. Puoi selezionare solo Swift o Objective-C e utilizzare o meno Core Data.

Ho provato a eliminare lo storyboard e dal progetto a rimuovere lo storyboard principale e a impostare manualmente la finestra da didFinishLaunching

In AppDelegate ho questo:

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

Tuttavia, XCode mi dà un errore:

La classe "AppDelegate" non ha inizializzatori

Qualcuno ci è riuscito?


Risposte:


71

È necessario contrassegnare le variabili windowe testNavigationControllercome facoltative:

var window : UIWindow?
var testNavigationController : UINavigationController?

Le classi Swift richiedono l'inizializzazione di proprietà non facoltative durante l'istanza:

Le classi e le strutture devono impostare tutte le loro proprietà memorizzate su un valore iniziale appropriato prima che venga creata un'istanza di quella classe o struttura. Le proprietà memorizzate non possono essere lasciate in uno stato indeterminato.

Le proprietà di tipo facoltativo vengono inizializzate automaticamente con un valore nil, a indicare che la proprietà è intenzionalmente destinata a non avere "ancora alcun valore" durante l'inizializzazione.

Quando si utilizzano variabili facoltative, ricordarsi di scartarle con !, ad esempio:

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

1
Tutto ha perfettamente senso nella tua risposta, fino alla fine. per favore spiegherai quell'ultima parte ?? scartare? è necessario?
DanMoore

1
Non è possibile memorizzare una proprietà non facoltativa nel proprio AppDelegate(a meno che non abbia un valore durante l'inizializzazione o non venga risolta pigramente). Se memorizzi una proprietà facoltativa e sei sicuro che non lo sia nil, "scartala dalla sua opzionalità" usando l' !operatore.
akashivskyy

qual è la migliore pratica, self.window! o usando if let window = ..?
laughingman

1
Se sei sicuro che la tua finestra esista (e puoi esserne sicuro in questo caso particolare), puoi andare con !.
akashivskyy

quindi questo significa che quando usiamo gli storyboard, il backgroundColor è in qualche modo impostato per impostazione predefinita .white?
Miele

91

Tutto ciò che serve per non utilizzare gli storyboard per rootViewController :

1 · Cambia AppDelegate.swiftin:

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 · Crea una ViewControllersottoclasse di UIViewController:

import UIKit

class ViewController: UIViewController {

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

3 · Se hai creato il progetto da un modello Xcode:

  1. Rimuovi la coppia chiave-valore per la chiave "Main storyboard file base name"daInfo.plist .
  2. Elimina il file dello storyboard Main.storyboard.

Come puoi vedere nel primo frammento di codice, invece di scartare implicitamente un opzionale, mi piace piuttosto la if letsintassi per scartare la windowproprietà opzionale . Qui lo sto usando in if let a = a { }modo che l'opzionale adiventi un riferimento non facoltativo all'interno ifdell'istruzione con lo stesso nome a.

Infine self.non è necessario quando si fa riferimento alla windowproprietà all'interno della propria classe.


1
Perché il if let window = window {? L'avevo capito! È così che non è necessario utilizzarlo window!ogni volta.
Bilal Akil

@ 2unco sono contento che tu l'abbia capito. Questo è descritto nell'ultima parte della mia risposta su if let a = a {}.
tobiasdm

Sposterei la chiamata makeKeyAndVisible()a essere dopo l' impostazione rootViewController. Altrimenti riceverai un avviso su come la finestra dovrebbe avere un controller di visualizzazione root alla fine del lancio dell'applicazione.
Sebastien Martin,

if let a = a { }sembra strano. Sei sicuro che sia corretto utilizzare lo stesso nome di variabile per il riferimento non facoltativo? Apple utilizza sempre nomi diversi nei propri documenti Swift. Inoltre, perché è meglio che usarlo window!ogni volta?
ma11hew28

1. if let a = a { }va benissimo. Puoi usarlo if let anA = a { }se ti fa sentire più a tuo agio. 2. window!è un controllo di runtime poiché si apre esplicitamente un opzionale. Mi piacciono i controlli in fase di compilazione che Swift ci fornisce, quindi perché non usarli.
tobiasdm

13

Se vuoi inizializzare il tuo viewController con xib e devi usare il controller di navigazione. Ecco un pezzo di codice.

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
}

6

Prova il codice seguente:

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

}

2

Ho trovato la risposta che non aveva nulla a che fare con la configurazione di xcode, rimuovere lo storyboard e il riferimento dal progetto è la cosa giusta. Aveva a che fare con la sintassi rapida.

Il codice è il seguente:

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
    }

}

Ma perché rispondere alla tua stessa domanda, se la soluzione è in un'altra risposta?
akashivskyy

la pagina non è stata aggiornata e non ho visto la risposta, solo dopo aver postato
EhTd

2

Puoi farlo in questo modo:

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

La finestra var: UIWindow? specificare che è una proprietà opzionale?
Sean Dunford

Bene, ho appena provato ad aggiungere una seconda var nel delegato dell'app senza di essa e ho trovato la mia affermazione sopra per essere vera.
Sean Dunford

2

Ti consiglio di usare controller e xib

MyViewController.swift e MyViewController.xib

(Puoi creare tramite File-> Nuovo-> File-> Cocoa Touch Class e impostare "crea anche file XIB" true, sottoclasse di UIViewController)

class MyViewController: UIViewController {
   .....    
}

e In AppDelegate.swift func applicationscrivi il codice seguente

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

Dovrebbe funzionare!


Ho provato nello stesso modo che hai menzionato ma errore: chiusura dell'app a causa di un'eccezione non rilevata "NSInternalInconsistencyException", motivo: "Impossibile caricare NIB nel pacchetto:
shripad20

2

Aggiornato per Swift 3.0:

window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()

2

Aggiornamento: Swift 5 e iOS 13:

  1. Crea un'applicazione a visualizzazione singola.
  2. Elimina Main.storyboard (fai clic con il pulsante destro del mouse ed elimina).
  3. Elimina il nome dello storyboard dalla configurazione della scena predefinita nel Info.plistfile:inserisci qui la descrizione dell'immagine
  4. Apri SceneDelegate.swifte cambia func sceneda:
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 }
}

per

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

1

Ecco un rapido esempio di test completo per 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
          }
    }

0

Perché non crei semplicemente un'applicazione vuota? lo storyboard non è stato creato per me ...


0

Possiamo creare un'applicazione basata sulla navigazione senza storyboard in Xcode 6 (iOS 8) come segue:

  • Crea un'applicazione vuota selezionando la lingua del progetto come Swift.

  • Aggiungi nuovi file di classe tocco cacao con l'interfaccia xib. (ad es. TestViewController)

  • In swift abbiamo un solo file che interagisce con il file xib, cioè * .swift, non ci sono file .h e .m.

  • Possiamo collegare i controlli di xib con il file swift come in iOS 7.

Di seguito sono riportati alcuni frammenti per lavorare con i controlli e 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()
    }

}

Modifiche nel file 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) {
    }

}

Trova un esempio di codice e altre informazioni su http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -Lavoro-con-i controlli /


0

In iOS 13 e versioni successive, quando crei un nuovo progetto senza storyboard, utilizza i passaggi seguenti:

  1. Crea progetto usando Xcode 11 o successivo

  2. Elimina pennino storyboard e classe

  3. Aggiungi un nuovo nuovo file con xib

  4. È necessario impostare la vista radice come UINavigationController SceneDelegate

  5. aggiungi sotto il codice func scene (_ scene: UIScene, willConnectTo session: UISceneSession, opzioni connectionOptions: UIScene.ConnectionOptions) {// Usa questo metodo per configurare e collegare facoltativamente la UIWindow windowalla UIWindowScene fornita scene. // Se si utilizza uno storyboard, la windowproprietà verrà automaticamente inizializzata e allegata alla scena. // Questo delegato non implica che la scena o la sessione di connessione siano nuove (vedere application:configurationForConnectingSceneSessioninvece). // guard let _ = (scene as? UIWindowScene) else {return}

    if let windowScene = scene as? UIWindowScene {self.window = UIWindow (windowScene: windowScene) lascia mainController = HomeViewController () come HomeViewController lascia navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController = navigationController self.window}.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.