【问题标题】:How do I create a new Swift project without using Storyboards?如何在不使用 Storyboard 的情况下创建新的 Swift 项目?
【发布时间】:2014-07-25 15:53:08
【问题描述】:

在 XCode 6 中创建新项目不允许禁用 Storyboard。您只能选择 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”类没有初始化器

有人成功了吗?

【问题讨论】:

标签: ios swift xcode6


【解决方案1】:

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· 创建UIViewControllerViewController 子类:

import UIKit

class ViewController: UIViewController {

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

3· 如果您从 Xcode 模板创建项目:

  1. Info.plist 中删除键 "Main storyboard file base name" 的键值对。
  2. 删除情节提要文件Main.storyboard

正如您在第一个代码 sn-p 中看到的那样,我更喜欢 if let 语法来解开可选的 window 属性,而不是隐式展开可选属性。在这里,我像if let a = a { } 一样使用它,以便可选的a 成为if 语句中具有相同名称的非可选引用-a

最后self. 在它自己的类中引用window 属性时是不必要的。

【讨论】:

  • 为什么是if let window = window {?我想到了!这样您就不需要每次都使用window!
  • @2unco 很高兴你知道了。这在我关于if let a = a {}的回答的最后一部分中有所描述。
  • 我会将呼叫转移到 makeKeyAndVisible() 以在 设置 rootViewController 之后进行。否则,您将收到有关在应用程序启动结束时窗口应如何具有根视图控制器的警告。
  • if let a = a { } 看起来很奇怪。您确定可以为非可选引用使用相同的变量名吗? Apple 在他们的 Swift 文档中总是使用不同的名称。另外,为什么这比每次都使用window! 更好?
  • 1. if let a = a { } 非常好。如果让您感觉更舒服,您可以使用if let anA = a { }。 2. window! 是运行时检查,因为您显式地打开了一个可选的。我喜欢 Swift 为我们提供的编译时检查,所以为什么不使用它。
【解决方案2】:

您必须将windowtestNavigationController 变量标记为可选:

var window : UIWindow?
var testNavigationController : UINavigationController?

Swift 类需要在实例化期间初始化非可选属性:

在创建该类或结构的实例时,类和结构必须将其所有存储的属性设置为适当的初始值。存储的属性不能处于不确定状态。

可选类型的属性会自动使用 nil 值进行初始化,这表明该属性在初始化期间故意设置为“还没有值”。

使用可选变量时,记得用!解包,如:

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

【讨论】:

  • 您的答案中的一切都非常有意义,直到最后。你能解释一下最后一部分吗?打开包装?这是必需的吗?
  • 您不能在AppDelegate 中存储非可选属性(除非它在初始化期间具有值,或者被延迟解析)。如果您存储了一个可选属性并且您确定它不是nil,则您可以使用! 运算符“将其从其可选性中解开”。
  • 最佳实践是什么,self.window!或使用 if let window = .. ?
  • 如果你确定你的窗口存在(并且在这种特殊情况下你可以确定),你可以选择!
  • 这是否意味着当我们使用故事板时,它的背景颜色默认为.white
【解决方案3】:

如果你想用 xib 初始化你的 viewController 并且需要使用导航控制器。这是一段代码。

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
}

【讨论】:

    【解决方案4】:

    试试下面的代码:

    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
    
    }
    

    【讨论】:

      【解决方案5】:

      我找到了答案,它与 xcode 设置无关,删除情节提要和从项目中引用是正确的。它与 swift 语法有关。

      代码如下:

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

      【讨论】:

      • 但是,如果解决方案在另一个答案中,为什么还要回答您自己的问题呢?
      • 页面没有更新也没有看到答案,发帖后才看到
      【解决方案6】:

      你可以这样做:

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

      【讨论】:

      • 是否 var window: UIWindow?指定它是一个可选属性?
      • 好吧,我只是尝试在没有它的情况下在应用程序委托中添加第二个 var,发现我的上述陈述是正确的。
      【解决方案7】:

      为 Swift 3.0 更新:

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

      【讨论】:

        【解决方案8】:

        更新: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 }
        }
        

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

        【讨论】:

          【解决方案9】:

          我推荐你使用控制器和xib

          MyViewController.swiftMyViewController.xib

          (可以通过File->New->File->Cocoa Touch Class创建,设置“也创建XIB文件”为true,UIViewController的子类)

          class MyViewController: UIViewController {
             .....    
          }
          

          并在AppDelegate.swiftfunc application写下以下代码

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

          应该可以了!

          【讨论】:

          • 我尝试了与您提到的相同的方式,但错误:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无法在捆绑包中加载 NIB:
          【解决方案10】:

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

          【讨论】:

            【解决方案11】:

            为什么不创建一个空的应用程序?故事板不是为我创建的...

            【讨论】:

              【解决方案12】:

              我们可以在 Xcode 6 (iOS 8) 中创建没有故事板的基于导航的应用程序,如下所示:

              • 通过选择项目语言来创建一个空应用程序 斯威夫特。

              • 使用接口 xib 添加新的 cocoa touch 类文件。 (例如。 测试视图控制器)

              • 在 swift 中,我们只有一个文件与 xib 交互,即 *.swift 文件,没有 .h 和 .m 文件。

              • 我们可以将xib的控件与iOS 7中一样的swift文件连接起来。

              以下是一些用于使用控件和 Swift 的 sn-ps

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

              【讨论】:

                【解决方案13】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-10-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-04-09
                  • 1970-01-01
                  • 2012-03-17
                  • 2016-01-15
                  • 1970-01-01
                  相关资源
                  最近更新 更多