Jak utworzyć nowy projekt Swift bez używania scenorysów?


107

Tworzenie nowego projektu w XCode 6 nie pozwala na wyłączenie scenorysów. Możesz wybrać tylko Swift lub Objective-C i użyć lub nie Core Data.

Próbowałem usunąć scenorys iz projektu usuwając główny scenorys i ręcznie ustawiając okno z didFinish Uruchamianie

W AppDelegate mam to:

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

Jednak XCode daje mi błąd:

Klasa „AppDelegate” nie ma inicjatorów

Czy komuś się to udało?


Odpowiedzi:


71

Musisz oznaczyć zmienne windowi testNavigationControllerjako opcjonalne:

var window : UIWindow?
var testNavigationController : UINavigationController?

Klasy Swift wymagają, aby podczas tworzenia instancji zostały zainicjowane właściwości, które nie są opcjonalne:

Klasy i struktury muszą ustawić wszystkie swoje przechowywane właściwości na odpowiednią wartość początkową do czasu utworzenia wystąpienia tej klasy lub struktury. Nie można pozostawić przechowywanych właściwości w stanie nieokreślonym.

Właściwości typu opcjonalnego są automatycznie inicjowane wartością nil, co oznacza, że ​​właściwość celowo ma mieć „jeszcze brak wartości” podczas inicjalizacji.

Korzystając ze zmiennych opcjonalnych, pamiętaj, aby je rozpakować !, takimi jak:

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

1
W Twojej odpowiedzi wszystko ma sens, aż do końca. czy możesz wyjaśnić tę ostatnią część? odwijać się? czy to jest wymagane?
— DanMoore,

1
Nie możesz przechowywać w swoim pliku właściwości, która nie jest opcjonalna AppDelegate(chyba że ma ona wartość podczas inicjalizacji lub zostanie rozwiązana leniwie). Jeśli przechowujesz opcjonalną właściwość i masz pewność, że tak nie jest nil, „rozpakuj ją z jej opcjonalności” za pomocą !operatora.
— akashivskyy

jaka jest najlepsza praktyka, self.window! lub używając if let window = ..?
— śmiech

1
Jeśli jesteś pewien, że Twoje okno istnieje (i możesz być pewien w tym konkretnym przypadku), możesz przejść z !.
— akashivskyy

więc czy to oznacza, że ​​kiedy używamy scenorysów, to w jakiś sposób domyślny kolor backgroundColor .white?
— Miód

91

Wszystko, czego potrzeba, aby nie używać scenorysów do rootViewController:

1 · Zmień AppDelegate.swiftna:

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 · Utwórz ViewControllerpodklasę UIViewController:

import UIKit

class ViewController: UIViewController {

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

3 · Jeśli utworzyłeś projekt z szablonu Xcode:

  1. Usuń parę klucz-wartość dla klucza "Main storyboard file base name" z Info.plist.
  2. Usuń plik storyboardu Main.storyboard .

Jak widać w pierwszym fragmencie kodu, zamiast niejawnie rozpakowywać opcjonalne, wolę if letskładnię rozpakowywania opcjonalnej windowwłaściwości. Tutaj używam go if let a = a { }tak, aby opcjonalne astało się nieopcjonalnym odniesieniem wewnątrzif nieopcjonalnym -statement o tej samej nazwie - a.

Wreszcie self.nie jest konieczne, gdy odwołujemy się do windowwłaściwości wewnątrz własnej klasy.


1
Dlaczego if let window = window {? Rozgryzłem to! Dzięki temu nie musisz go używać za window!każdym razem.
— Bilal Akil

@ 2unco Cieszę się, że to rozgryzłeś. Jest to opisane w ostatniej części mojej odpowiedzi na temat if let a = a {}.
— tobiasdm

Chciałbym przenieść wezwanie do makeKeyAndVisible()bycia po ustawieniu rootViewController. W przeciwnym razie otrzymasz ostrzeżenie o tym, jak oczekuje się, że okno będzie miało główny kontroler widoku pod koniec uruchamiania aplikacji.
— Sebastien Martin

if let a = a { }wygląda dziwnie. Czy na pewno można użyć tej samej nazwy zmiennej dla nieopcjonalnego odwołania? Apple zawsze używa różnych nazw w swoich dokumentach Swift. Dlaczego jest to lepsze niż zwykłe używanie za window!każdym razem?
— ma11hew28

1. if let a = a { }jest całkowicie w porządku. Możesz użyć, if let anA = a { }jeśli poczujesz się bardziej komfortowo. 2. window!jest sprawdzaniem w czasie wykonywania, ponieważ jawnie rozpakowujesz opcjonalny. Podoba mi się sprawdzanie czasu kompilacji, które zapewnia nam Swift, więc dlaczego go nie użyć.
— tobiasdm

13

Jeśli chcesz zainicjować swój viewController za pomocą xib i i potrzebujesz użyć kontrolera nawigacji. Oto fragment kodu.

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

Wypróbuj następujący kod:

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

Znalazłem odpowiedź, że nie ma to nic wspólnego z konfiguracją xcode, usunięcie scenorysu i odniesienia z projektu jest właściwe. Miało to związek z szybką składnią.

Kod jest następujący:

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
    }

}

Ale po co odpowiadać na własne pytanie, skoro rozwiązaniem jest inna odpowiedź?
— akashivskyy

strona nie była aktualizowana i nie widziałem odpowiedzi, dopiero po wysłaniu
— EhTd

2

Możesz to zrobić w ten sposób:

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

Czy var window: UIWindow? określić, że jest to właściwość opcjonalna?
— Sean Dunford

Po prostu próbowałem dodać drugi delegat var w aplikacji bez niego i stwierdziłem, że moje powyższe stwierdzenie jest prawdą.
— Sean Dunford

2

Zalecam użycie kontrolera i XIB

MyViewController.swift i MyViewController.xib

(Możesz utworzyć za pomocą File-> New-> File-> Cocoa Touch Class i ustawić „także utwórz plik XIB” true, podklasę UIViewController)

class MyViewController: UIViewController {
   .....    
}

i AppDelegate.swift func applicationnapisz następujący kod

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

Powinno pracować!


Próbowałem w ten sam sposób, o którym wspomniałeś, ale błąd: Zamykanie aplikacji z powodu nieprzechwyconego wyjątku „NSInternalInconsistencyException”, powód: „Nie można załadować NIB w pakiecie:
— shripad20

2

Zaktualizowano dla Swift 3.0:

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

2

Aktualizacja: Swift 5 i iOS 13:

  1. Utwórz aplikację z pojedynczym widokiem.
  2. Usuń Main.storyboard (kliknij prawym przyciskiem myszy i usuń).
  3. Usuń nazwę scenorysu z domyślnej konfiguracji sceny w Info.plistpliku:wprowadź opis obrazu tutaj
  4. Otwórz SceneDelegate.swifti zmień func scenez:
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 }
}

do

 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

Oto przykład pełnego szybkiego testu dla kontrolera 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

Dlaczego po prostu nie utworzysz pustej aplikacji? scenorys nie jest dla mnie stworzony ...


0

Możemy stworzyć aplikację nawigacyjną bez scenorysu w Xcode 6 (iOS 8) w następujący sposób:

  • Utwórz pustą aplikację, wybierając język projektu jako Swift.

  • Dodaj nowe pliki klas dotykowych cocoa z interfejsem xib. (np. TestViewController)

  • W szybkim mamy tylko jeden plik wchodzący w interakcję z xib, tj. Plik * .swift, nie ma plików .h i .m.

  • Sterowanie xib możemy połączyć z plikiem swift takim samym, jak w iOS 7.

Poniżej znajduje się kilka fragmentów do pracy z kontrolkami i 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()
    }

}

Zmiany w pliku 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) {
    }

}

Znajdź przykład kodu i inne informacje na http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -praca-z-sterowaniem /


0

W systemie iOS 13 i nowszych podczas tworzenia nowego projektu bez scenorysu użyj poniższych kroków:

  1. Utwórz projekt za pomocą Xcode 11 lub nowszego

  2. Usuń końcówkę i klasę scenorysu

  3. Dodaj nowy plik za pomocą xib

  4. Należy ustawić widok główny jako UINavigationController SceneDelegate

  5. dodaj poniżej kod func scene (_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {// Użyj tej metody, aby opcjonalnie skonfigurować i dołączyć UIWindow windowdo podanego UIWindowScene scene. // Jeśli używasz scenorysu, windowwłaściwość zostanie automatycznie zainicjowana i dołączona do sceny. // Ten delegat nie oznacza, że ​​łącząca scena lub sesja są nowe (patrzapplication:configurationForConnectingSceneSession zamiast tego). // straż niech _ = (scena jako? UIWindowScene) else {return}

    jeśli niech windowScene = scena jako? UIWindowScene {self.window = UIWindow (windowScene: windowScene) let mainController = HomeViewController () as HomeViewController let navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController = navigationContrible.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.