Wie erstelle ich ein neues Swift-Projekt ohne Storyboards?

107

Beim Erstellen eines neuen Projekts in XCode 6 können Storyboards nicht deaktiviert werden. Sie können nur Swift oder Objective-C auswählen und Core Data verwenden oder nicht.

Ich habe versucht, das Storyboard zu löschen und aus dem Projekt das Haupt-Storyboard zu entfernen und das Fenster von didFinishLaunching manuell festzulegen

Im AppDelegate habe ich folgendes:

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

XCode gibt mir jedoch einen Fehler:

Die Klasse 'AppDelegate' hat keine Initialisierer

Hat das jemand geschafft?

EhTd
quelle
1
Mögliches Duplikat von So erstellen Sie eine leere Anwendung in Xcode 6 ohne Storyboard
S1LENT WARRIOR

Antworten:

71

Sie müssen die Variablen windowund testNavigationControllerals optional markieren :

var window : UIWindow?
var testNavigationController : UINavigationController?

Bei Swift-Klassen müssen nicht optionale Eigenschaften während der Instanziierung initialisiert werden:

Klassen und Strukturen müssen alle ihre gespeicherten Eigenschaften auf einen geeigneten Anfangswert setzen, wenn eine Instanz dieser Klasse oder Struktur erstellt wird. Gespeicherte Eigenschaften können nicht in einem unbestimmten Zustand belassen werden.

Eigenschaften vom optionalen Typ werden automatisch mit dem Wert Null initialisiert, was darauf hinweist, dass die Eigenschaft während der Initialisierung absichtlich "noch keinen Wert" haben soll.

Denken Sie bei der Verwendung optionaler Variablen daran, diese zu entpacken !, z.

self.window!.backgroundColor = UIColor.whiteColor();
akashivskyy
quelle
1
In Ihrer Antwort macht bis zum Ende alles Sinn. Würdest du bitte diesen letzten Teil erklären? auspacken? ist das erforderlich?
DanMoore
1
Sie können eine nicht optionale Eigenschaft nicht in Ihrer speichern AppDelegate(es sei denn, sie hat während der Initialisierung einen Wert oder wird träge aufgelöst). Wenn Sie eine optionale Eigenschaft speichern und sicher sind , dass dies nicht der nilFall ist, "entpacken Sie sie mit dem !Operator von ihrer Optionalität" .
Akashivskyy
Was ist die beste Vorgehensweise, self.window! oder mit if let window = ..?
Lachender
1
Wenn Sie sicher sind, dass Ihr Fenster vorhanden ist (und Sie können in diesem speziellen Fall sicher sein), können Sie mit gehen !.
Akashivskyy
Bedeutet dies also, wenn wir Storyboards verwenden, dass die Hintergrundfarbe irgendwie standardmäßig verwendet wird .white?
Honig
91

Alles, was Sie brauchen, um Storyboards nicht zu verwenden für rootViewController:

1 · Wechseln AppDelegate.swiftzu:

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 · Erstellen Sie eine ViewControllerUnterklasse von UIViewController:

import UIKit

class ViewController: UIViewController {

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

3 · Wenn Sie das Projekt aus einer Xcode-Vorlage erstellt haben:

  1. Entfernen Sie das Schlüssel-Wert-Paar für den Schlüssel "Main storyboard file base name"aus Info.plist.
  2. Löschen Sie die Storyboard-Datei Main.storyboard.

Wie Sie im ersten Codeausschnitt sehen können, gefällt mir die if letSyntax zum Entpacken der optionalen windowEigenschaft eher, anstatt implizit ein optionales zu entpacken . Hier verwende ich es if let a = a { }so, dass das optionale aeine nicht optionale Referenz innerhalb der gleichnamigen ifAnweisung wird - a.

Schließlich self.ist es nicht erforderlich, auf die windowEigenschaft innerhalb der eigenen Klasse zu verweisen .

Tobiasdm
quelle
1
Warum das if let window = window {? Ich habe es herausgefunden! Es ist so, dass Sie nicht window!jedes Mal verwenden müssen.
Bilal Akil
@ 2unco Ich bin froh, dass du es herausgefunden hast. Dies wird im letzten Teil meiner Antwort über beschrieben if let a = a {}.
Tobiasdm
Ich würde den Anruf verschieben makeKeyAndVisible(), um nach dem Einstellen zu sein rootViewController. Andernfalls erhalten Sie eine Warnung darüber, wie das Fenster am Ende des Anwendungsstarts voraussichtlich einen Root-View-Controller haben wird.
Sebastien Martin
if let a = a { }sieht komisch aus. Sind Sie sicher, dass es in Ordnung ist, denselben Variablennamen für die nicht optionale Referenz zu verwenden? Apple verwendet in seinen Swift-Dokumenten immer unterschiedliche Namen. Warum ist das besser als window!jedes Mal zu verwenden?
ma11hew28
1. if let a = a { }ist vollkommen in Ordnung. Sie können verwenden, if let anA = a { }wenn Sie sich dadurch wohler fühlen. 2. window!ist eine Laufzeitprüfung, da Sie eine Option explizit auspacken. Ich mag die Überprüfungen der Kompilierungszeit, die Swift uns zur Verfügung stellt. Warum also nicht?
Tobiasdm
13

Wenn Sie Ihren viewController mit xib initialisieren möchten und den Navigationscontroller verwenden möchten. Hier ist ein Stück 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
quelle
6

Versuchen Sie den folgenden Code:

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
quelle
2

Ich habe die Antwort gefunden, die nichts mit dem Xcode-Setup zu tun hat. Das Entfernen des Storyboards und der Referenz aus dem Projekt ist das Richtige. Es hatte mit der schnellen Syntax zu tun.

Der Code lautet wie folgt:

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
quelle
Aber warum Ihre eigene Frage beantworten, wenn die Lösung in einer anderen Antwort liegt?
Akashivskyy
Die Seite wurde nicht aktualisiert und ich habe die Antwort erst nach dem Posten gesehen
EhTd
2

Sie können es einfach so machen:

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
quelle
Hat var window: UIWindow? Geben Sie an, dass es sich um eine optionale Eigenschaft handelt.
Sean Dunford
Nun, ich habe gerade versucht, eine zweite Variable in App Delegate ohne diese hinzuzufügen, und fand meine obige Aussage wahr.
Sean Dunford
2

Ich empfehle Ihnen, Controller und xib zu verwenden

MyViewController.swift und MyViewController.xib

(Sie können über Datei-> Neu-> Datei-> Cocoa Touch-Klasse erstellen und "Auch XIB-Datei erstellen" auf true setzen, Unterklasse von UIViewController)

class MyViewController: UIViewController {
   .....    
}

und AppDelegate.swift func applicationSchreiben Sie den folgenden Code

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

Es sollte Arbeit sein!

Yi Feng Xie
quelle
Ich habe auf die gleiche Weise versucht, wie Sie es erwähnt haben, aber Fehler: Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInternalInconsistencyException', Grund: 'NIB konnte nicht im Bundle
geladen werden
2

Aktualisiert für Swift 3.0:

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

Update: Swift 5 und iOS 13:

  1. Erstellen Sie eine Single View-Anwendung.
  2. Löschen Main.storyboard (Rechtsklick und Löschen).
  3. Löschen Sie den Storyboard-Namen aus der Standard-Szenenkonfiguration in der Info.plistDatei:Geben Sie hier die Bildbeschreibung ein
  4. Öffnen SceneDelegate.swiftund ändern func scenevon:
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 }
}

zu

 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
quelle
1

Hier ist ein vollständiges Beispiel für einen schnellen Test für einen 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
quelle
0

Warum erstellen Sie nicht einfach eine leere Anwendung? Das Storyboard ist für mich nicht erstellt ...

allemattio
quelle
0

Wir können eine navigationsbasierte Anwendung ohne Storyboard in Xcode 6 (iOS 8) wie folgt erstellen:

  • Erstellen Sie eine leere Anwendung, indem Sie die Projektsprache als Swift auswählen.

  • Fügen Sie mit der Schnittstelle xib neue Cocoa Touch-Klassendateien hinzu. (zB TestViewController)

  • Im Swift haben wir nur eine Datei, die mit der xib interagiert, dh * .swift-Datei, es gibt keine .h- und .m-Dateien.

  • Wir können die Steuerelemente von xib mit einer schnellen Datei wie in iOS 7 verbinden.

Im Folgenden finden Sie einige Ausschnitte für die Arbeit mit den Steuerelementen und 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()
    }

}

Änderungen in der Datei 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) {
    }

}

Codebeispiel und andere Informationen finden Sie unter http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -arbeit-mit-steuern /

Ashish Kakkad
quelle
0

In iOS 13 und höher, wenn Sie ein neues Projekt ohne Storyboard erstellen, gehen Sie wie folgt vor:

  1. Erstellen Sie ein Projekt mit Xcode 11 oder höher

  2. Löschen Sie die Storyboard-Feder und die Klasse

  3. Neue neue Datei mit xib hinzufügen

  4. Die Stammansicht muss als UINavigationController SceneDelegate festgelegt werden

  5. Fügen Sie den folgenden Code hinzu: func scene (_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {// Verwenden Sie diese Methode, um das UIWindow optional zu konfigurieren und an windowdas bereitgestellte UIWindowScene anzuhängen scene. // Wenn Sie ein Storyboard verwenden, wird die windowEigenschaft automatisch initialisiert und an die Szene angehängt. // Dieser Delegat bedeutet nicht, dass die Verbindungsszene oder Sitzung neu ist (siehe application:configurationForConnectingSceneSessionstattdessen). // Wache let _ = (Szene als? UIWindowScene) else {return}

    wenn let windowScene = szene als? UIWindowScene {self.window = UIWindow (windowScene: windowScene) let mainController = HomeViewController () als HomeViewController let navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController!

Yogesh Shelke
quelle