Как создать новый проект Swift без использования раскадровок?

Создание нового проекта в XCode 6 не позволяет отключить раскадровки. Вы можете выбрать только Swift или Objective-C и использовать или не использовать Core Data.

Я попытался удалить раскадровку и из проекта удалить основную раскадровку и вручную установить окно из didFinishLaunching

В AppDelegate у меня есть это:

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 выдает ошибку:

Класс AppDelegate не имеет инициализаторов

Кому-нибудь это удалось?


person EhTd    schedule 04.06.2014    source источник
comment
Возможный дубликат Как создать пустое приложение в Xcode 6 без раскадровки   -  person S1LENT WARRIOR    schedule 25.04.2016


Ответы (13)


Вы должны пометить переменные window и testNavigationController как необязательные:

var window : UIWindow?
var testNavigationController : UINavigationController?

Классы Swift требуют инициализации необязательных свойств во время создания экземпляра:

Классы и структуры должны установить для всех своих сохраненных свойств соответствующее начальное значение к моменту создания экземпляра этого класса или структуры. Сохраненные свойства нельзя оставлять в неопределенном состоянии.

Свойства необязательного типа автоматически инициализируются значением nil, что указывает на то, что свойство намеренно предназначено для того, чтобы «еще не иметь значения» во время инициализации.

При использовании необязательных переменных не забудьте развернуть их с помощью !, например:

self.window!.backgroundColor = UIColor.whiteColor();
person akashivskyy    schedule 04.06.2014
comment
В вашем ответе все до конца имеет смысл. не могли бы вы объяснить последнюю часть ?? развернуть? это требуется? - person DanMoore; 10.09.2014
comment
Вы не можете сохранить необязательное свойство в своем AppDelegate (если оно не имеет значения во время инициализации или не разрешается лениво). Если вы сохраняете необязательное свойство и уверены, что это не nil, разверните его из его необязательного свойства с помощью оператора !. - person akashivskyy; 10.09.2014
comment
что лучше всего, self.window! или используя if let window = ..? - person Sai Prasanna; 20.02.2015
comment
Если вы уверены, что ваше окно существует (и вы можете быть уверены в этом конкретном случае), вы можете использовать !. - person akashivskyy; 20.02.2015
comment
Значит ли это, что когда мы используем раскадровки, backgroundColor каким-то образом по умолчанию имеет значение .white? - person Honey; 28.11.2017

Все, что нужно, чтобы не использовать раскадровки для rootViewController:

1 · Измените AppDelegate.swift на:

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 · Создайте ViewController подкласс UIViewController:

import UIKit

class ViewController: UIViewController {

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

3 · Если вы создали проект из шаблона Xcode:

  1. Удалите пару "ключ-значение" для ключа "Main storyboard file base name" из Info.plist.
  2. Удалите файл раскадровки Main.storyboard.

Как вы можете видеть в первом фрагменте кода, вместо неявного разворачивания необязательного свойства мне больше нравится синтаксис if let для разворачивания необязательного свойства window. Здесь я использую его как if let a = a { }, чтобы необязательный a стал необязательной ссылкой внутри if-оператора с тем же именем - a.

Наконец, self. не требуется при ссылке на свойство window внутри своего собственного класса.

person tobiasdm    schedule 25.08.2014
comment
Почему if let window = window {? Я понял! Это значит, что вам не нужно использовать window! каждый раз. - person Bilal Akil; 19.10.2014
comment
@ 2unco Я рада, что ты все понял. Это описано в последней части моего ответа о if let a = a {}. - person tobiasdm; 20.10.2014
comment
Я бы переместил вызов на makeKeyAndVisible(), чтобы он был после установки rootViewController. В противном случае вы получите предупреждение о том, что в конце запуска приложения ожидается наличие в окне корневого контроллера представления. - person Sebastien Martin; 27.12.2014
comment
if let a = a { } выглядит странно. Вы уверены, что можно использовать то же имя переменной для необязательной ссылки? Apple всегда использует разные имена в своих документах Swift. Кроме того, почему это лучше, чем просто использовать window! каждый раз? - person ma11hew28; 25.04.2015
comment
1. if let a = a { } в порядке. Вы можете использовать if let anA = a { }, если вам так удобнее. 2. window! - это проверка во время выполнения, поскольку вы явно разворачиваете необязательный. Мне нравятся проверки времени компиляции, которые предоставляет нам Swift, так почему бы не использовать его. - person tobiasdm; 30.04.2015
comment
Спасибо, m8! Начинаю с Swift сегодня, так что все как-то странно (: - person Felipe; 27.10.2015
comment
В результате сверху и снизу ViewControllers появляется черная линия размером 1 пиксель. Есть подсказки, как от этого избавиться? (Не используется Launch.storyboard файл - person jdev; 11.03.2017
comment
@jdev Это не похоже на этот ответ. - person tobiasdm; 13.03.2017
comment
@duemunk: Извините, я думал, что это ... Если я полностью удалю раскадровки из моего проекта шаблона (включая Launch.storyboard), то я увижу линию размером 1 пиксель вверху и внизу экрана. Я не знал почему, и, похоже, это было связано с отсутствием раскадровки, потому что, если я создаю новую раскадровку и устанавливаю ее как Launch Screen File, строки исчезают, поэтому я подумал, что могу спросить. Поскольку требовалось не использовать раскадровку, после их удаления я добавил белый LaunchImage (во всех необходимых разрешениях) к xcasset, и черные линии исчезли .. - person jdev; 13.03.2017

Если вы хотите инициализировать свой viewController с помощью xib и вам нужно использовать контроллер навигации. Вот фрагмент кода.

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
}
person Warewolf    schedule 07.11.2014

Попробуйте следующий код:

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

}
person PREMKUMAR    schedule 05.06.2014

Я нашел ответ, который не имеет ничего общего с настройкой xcode, удаление раскадровки и ссылки из проекта - это правильно. Это было связано с быстрым синтаксисом.

Код следующий:

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
    }

}
person EhTd    schedule 04.06.2014
comment
Но зачем отвечать на свой вопрос, если решение в другом ответе? - person akashivskyy; 05.06.2014
comment
страница не обновлялась и я не видел ответа, только после публикации - person EhTd; 05.06.2014

Вы можете сделать это так:

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
    }
}
person Hilen    schedule 06.06.2014
comment
Есть ли var window: UIWindow? указать, что это необязательное свойство? - person Sean Dunford; 13.06.2014
comment
Ну, я просто попытался добавить второй var в делегат приложения без него и обнаружил, что мое приведенное выше утверждение верно. - person Sean Dunford; 13.06.2014

Я рекомендую вам использовать контроллер и xib

MyViewController.swift и MyViewController.xib

(Вы можете создать через File-> New-> File-> Cocoa Touch Class и установить "также создать файл XIB" true, подкласс UIViewController)

class MyViewController: UIViewController {
   .....    
}

и в AppDelegate.swift func application напишите следующий код

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

Надо работать!

person Yi Feng Xie    schedule 09.06.2014
comment
Я пробовал так же, как вы упомянули, но с ошибкой: завершение работы приложения из-за неперехваченного исключения «NSInternalInconsistencyException», причина: «Не удалось загрузить NIB в связке: - person shripad20; 31.07.2014

Обновлено для Swift 3.0:

window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
person Tiago Martinho    schedule 23.02.2017

Обновление: Swift 5 и iOS 13:

  1. Создайте приложение с одним представлением.
  2. Удалите Main.storyboard (щелкните правой кнопкой мыши и удалите).
  3. Удалите Имя раскадровки из конфигурации сцены по умолчанию в Info.plist файле: введите описание изображения здесь
  4. Откройте SceneDelegate.swift и измените func scene с:
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 }
}

to

 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()
    }
}
person Jogendra Kumar    schedule 22.10.2019

Вот полный пример быстрого теста для 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
          }
    }
person Dmitry Konovalov    schedule 20.05.2015

Почему бы вам просто не создать пустое приложение? раскадровка не создана для меня ...

person allemattio    schedule 09.06.2014

Мы можем создать приложение на основе навигации без раскадровки в Xcode 6 (iOS 8) следующим образом:

  • Создайте пустое приложение, выбрав язык проекта Swift.

  • Добавьте новые файлы классов касания какао с помощью интерфейса xib. (например, TestViewController)

  • В swift у нас есть только один файл, взаимодействующий с xib, т.е. файл * .swift, файлов .h и .m нет.

  • Мы можем связать элементы управления xib с быстрым файлом так же, как в iOS 7.

Ниже приведены некоторые фрагменты для работы с элементами управления и 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()
    }

}

Изменения в файле 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) {
    }

}

Найдите образец кода и другую информацию на http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and-work-with-controls/

person Ashish Kakkad    schedule 24.06.2014

В iOS 13 и выше при создании нового проекта без раскадровки используйте следующие шаги:

  1. Создать проект с использованием Xcode 11 или выше
  2. Удалить перо раскадровки и класс
  3. Добавить новый файл с помощью xib
  4. Необходимо установить корневое представление как UINavigationController SceneDelegate
  5. добавьте ниже код:
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 }
    
    if let windowScene = scene as? UIWindowScene {
        self.window = UIWindow(windowScene: windowScene)
        let mainController = HomeViewController() as HomeViewController
        let navigationController = UINavigationController(rootViewController: mainController)
        self.window!.rootViewController = navigationController
        self.window!.makeKeyAndVisible()
    }
}
person Yogesh shelke    schedule 27.07.2020