Como faço para criar um novo projeto Swift sem usar Storyboards?


107

Criar um novo projeto no XCode 6 não permite desabilitar Storyboards. Você só pode selecionar Swift ou Objective-C e usar ou não Core Data.

Tentei deletar o storyboard e do projeto removendo o storyboard principal e configurando manualmente a janela em didFinishLaunching

No AppDelegate, tenho o seguinte:

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

No entanto, o XCode me dá um erro:

A classe 'AppDelegate' não tem inicializadores

Alguém conseguiu isso?


Respostas:


71

Você deve marcar as variáveis windowe testNavigationControllercomo opcionais:

var window : UIWindow?
var testNavigationController : UINavigationController?

As classes Swift requerem que propriedades não opcionais sejam inicializadas durante a instanciação:

As classes e estruturas devem definir todas as suas propriedades armazenadas com um valor inicial apropriado no momento em que uma instância dessa classe ou estrutura é criada. Propriedades armazenadas não podem ser deixadas em um estado indeterminado.

Propriedades de tipo opcional são inicializadas automaticamente com um valor nil, indicando que a propriedade foi intencionalmente destinada a ter “nenhum valor ainda” durante a inicialização.

Ao usar variáveis ​​opcionais, lembre-se de desembrulhá-las com !, como:

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

1
Tudo faz sentido na sua resposta, até o fim. você poderia explicar essa última parte ?? desembrulhar? isso é necessário?
DanMoore

1
Você não pode armazenar uma propriedade não opcional em seu AppDelegate(a menos que tenha um valor durante a inicialização ou seja resolvido lentamente). Se você armazenar uma propriedade opcional e tiver certeza de que não é nil, "desembrulhe-a de sua opcionalidade" usando o !operador.
akashivskyy de

qual é a melhor prática, self.window! ou usando if let window = ..?
laughman

1
Se você tiver certeza de que sua janela existe (e você pode ter certeza neste caso em particular), pode prosseguir !.
akashivskyy

então isso significa que quando usamos storyboards, o backgroundColor é de alguma forma padronizado .white?
Honey

91

Basta não usar Storyboards para rootViewController:

1 · Mude AppDelegate.swiftpara:

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 · Crie uma ViewControllersubclasse de UIViewController:

import UIKit

class ViewController: UIViewController {

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

3. Se você criou o projeto a partir de um modelo Xcode:

  1. Remova o par de valores-chave para a chave "Main storyboard file base name"de Info.plist.
  2. Exclua o arquivo de storyboard Main.storyboard.

Como você pode ver no primeiro fragmento de código, em vez de desembrulhar implicitamente um opcional, prefiro a if letsintaxe para desembrulhar a windowpropriedade opcional . Aqui, estou usando-o if let a = a { }para que o opcional ase torne uma referência não opcional dentro da ifinstrução -com o mesmo nome - a.

Finalmente, self.não é necessário ao fazer referência à windowpropriedade dentro de sua própria classe.


1
Por que if let window = window {? Eu descobri! É assim que você não precisa usar window!todas as vezes.
Bilal Akil

@ 2unco Fico feliz que você tenha descoberto. Isso é descrito na última parte da minha resposta sobre if let a = a {}.
tobiasdm

Gostaria de passar a chamada para makeKeyAndVisible()ser , após ajuste rootViewController. Caso contrário, você receberá um aviso sobre como se espera que a janela tenha um controlador de visualização raiz no final da inicialização do aplicativo.
Sebastien Martin

if let a = a { }Parece estranho. Tem certeza de que pode usar o mesmo nome de variável para a referência não opcional? A Apple sempre usa nomes diferentes em seus documentos Swift. Além disso, por que isso é melhor do que apenas usar window!sempre?
ma11hew28

1. if let a = a { }está perfeitamente bem. Você pode usar if let anA = a { }se sentir mais confortável. 2. window!é uma verificação de tempo de execução, já que você desdobra explicitamente um opcional. Eu gosto das verificações de tempo de compilação que o Swift nos fornece, então por que não usá-lo.
tobiasdm

13

Se você deseja inicializar seu viewController com xib e precisa usar o controlador de navegação. Aqui está um trecho de código.

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

Experimente o seguinte código:

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

Eu encontrei a resposta que não tinha nada a ver com a configuração do xcode, remover o storyboard e a referência do projeto é a coisa certa. Tinha a ver com a sintaxe rápida.

O código é o seguinte:

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
    }

}

Mas por que responder à sua própria pergunta, se a solução está em outra resposta?
akashivskyy

a página não foi atualizada e eu não vi a resposta, somente após postar
EhTd

2

Você pode fazer assim:

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

A janela var: UIWindow? especificar que é uma propriedade opcional?
Sean Dunford

Bem, eu apenas tentei adicionar uma segunda var no delegado do aplicativo sem ela e descobri que minha afirmação acima era verdadeira.
Sean Dunford

2

Eu recomendo que você use controlador e xib

MyViewController.swift e MyViewController.xib

(Você pode criar através de Arquivo-> Novo-> Arquivo-> Classe Cocoa Touch e definir "também criar arquivo XIB" true, subclasse de UIViewController)

class MyViewController: UIViewController {
   .....    
}

e em AppDelegate.swift func applicationescrever o seguinte código

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

Deve dar certo!


Tentei da mesma maneira que você mencionou, mas erro: Encerrando o aplicativo devido à exceção não capturada 'NSInternalInconsistencyException', motivo: 'Não foi possível carregar o NIB no pacote:
shripad20

2

Atualizado para Swift 3.0:

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

2

Atualização: Swift 5 e iOS 13:

  1. Crie um aplicativo de visualização única.
  2. Exclua Main.storyboard (clique com o botão direito e exclua).
  3. Exclua o nome do storyboard da configuração padrão da cena no Info.plistarquivo:insira a descrição da imagem aqui
  4. Abra SceneDelegate.swifte mude 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 }
}

para

 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

Aqui está um exemplo de teste rápido completo para um 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

Por que você simplesmente não cria um aplicativo vazio? o storyboard não foi criado para mim ...


0

Podemos criar aplicativos baseados em navegação sem storyboard no Xcode 6 (iOS 8) da seguinte maneira:

  • Crie um aplicativo vazio selecionando o idioma do projeto como Swift.

  • Adicione novos arquivos de classe de toque cacau com a interface xib. (por exemplo, TestViewController)

  • No swift, temos apenas um arquivo interagindo com o xib, ou seja, arquivo * .swift, não há arquivos .h e .m.

  • Podemos conectar os controles do xib com o arquivo swift mesmo que no iOS 7.

A seguir estão alguns trechos para trabalhar com os controles 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()
    }

}

Alterações no arquivo 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) {
    }

}

Encontre amostra de código e outras informações em http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -trabalho-com-controles /


0

No iOS 13 e superior, ao criar um novo projeto sem storyboard, use as etapas abaixo:

  1. Crie um projeto usando o Xcode 11 ou superior

  2. Excluir a ponta e a classe do storyboard

  3. Adicionar novo arquivo com o xib

  4. É necessário definir a visualização raiz como UINavigationController SceneDelegate

  5. adicionar abaixo o código func scene (_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {// Use este método para configurar opcionalmente e anexar o UIWindow windowao UIWindowScene fornecido scene. // Se estiver usando um storyboard, a windowpropriedade será inicializada automaticamente e anexada à cena. // Este delegado não implica que a cena ou sessão de conexão sejam novas (veja ao application:configurationForConnectingSceneSessioninvés). // guarda let _ = (cena como? UIWindowScene) else {return}

    se deixar windowScene = scene como? UIWindowScene {self.window = UIWindow (windowScene: windowScene) let mainController = HomeViewController () as HomeViewController let navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController = navigationController self.window}.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.