ฉันจะสร้างโครงการ Swift ใหม่โดยไม่ใช้สตอรี่บอร์ดได้อย่างไร


107

การสร้างโปรเจ็กต์ใหม่ใน XCode 6 ไม่อนุญาตให้ปิดใช้งานสตอรี่บอร์ด คุณสามารถเลือกได้เฉพาะ Swift หรือ Objective-C และจะใช้หรือไม่ใช้ข้อมูลหลัก

ฉันพยายามลบสตอรี่บอร์ดและจากโปรเจ็กต์ลบสตอรี่บอร์ดหลักและตั้งค่าหน้าต่างด้วยตนเองจาก 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' ไม่มีตัวเริ่มต้น

มีใครประสบความสำเร็จในเรื่องนี้บ้าง?


คำตอบ:


71

คุณต้องทำเครื่องหมายwindowและtestNavigationControllerตัวแปรเป็นทางเลือก:

var window : UIWindow?
var testNavigationController : UINavigationController?

คลาส Swift ต้องการคุณสมบัติที่ไม่ใช่ทางเลือกเพื่อเตรียมใช้งานในระหว่างการสร้างอินสแตนซ์:

คลาสและโครงสร้างต้องตั้งค่าคุณสมบัติที่เก็บไว้ทั้งหมดให้เป็นค่าเริ่มต้นที่เหมาะสมตามเวลาที่สร้างอินสแตนซ์ของคลาสหรือโครงสร้างนั้น คุณสมบัติที่จัดเก็บไว้ไม่สามารถปล่อยให้อยู่ในสถานะที่ไม่แน่นอน

คุณสมบัติของชนิดที่เป็นทางเลือกจะถูกกำหนดค่าเริ่มต้นโดยอัตโนมัติโดยมีค่าเป็นศูนย์ซึ่งแสดงว่าคุณสมบัตินั้นตั้งใจให้มี“ ยังไม่มีค่า” ในระหว่างการเริ่มต้น

เมื่อใช้ตัวแปรเสริมอย่าลืมแกะออกด้วย!เช่น:

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

1
ทุกอย่างสมเหตุสมผลในคำตอบของคุณจนถึงที่สุด ช่วยอธิบายส่วนสุดท้ายได้ไหม ?? แกะ? จำเป็นไหม
DanMoore

1
คุณไม่สามารถจัดเก็บคุณสมบัติที่ไม่เป็นทางเลือกในของคุณAppDelegate(เว้นแต่ว่าจะมีค่าระหว่างการเริ่มต้นหรือได้รับการแก้ไขอย่างเฉื่อยชา) หากคุณจัดเก็บพร็อพเพอร์ตี้ที่เป็นทางเลือกและแน่ใจว่าไม่ใช่nilคุณจะ "แกะมันออกจากตัวเลือก" โดยใช้!โอเปอเรเตอร์
akashivskyy

แนวทางปฏิบัติที่ดีที่สุดคืออะไร self.window! หรือใช้ if let window = .. ?
หัวเราะ

1
หากคุณแน่ใจว่ามีหน้าต่างของคุณอยู่ (และคุณมั่นใจได้ในกรณีนี้โดยเฉพาะ) คุณสามารถไป!ได้
akashivskyy

นี่หมายความว่าเมื่อเราใช้สตอรีบอร์ดพื้นหลังสีมันผิดนัด.whiteหรือไม่?
น้ำผึ้ง

91

สิ่งที่ต้องทำเพื่อไม่ใช้ Storyboards สำหรับ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-statement ที่มีชื่อเดียวกัน a-

สุดท้ายself.ไม่จำเป็นเมื่ออ้างอิงwindowคุณสมบัติภายในคลาสของตัวเอง


1
ทำไมif let window = window {? ฉันคิดออกแล้ว! ดังนั้นคุณไม่จำเป็นต้องใช้window!ทุกครั้ง
Bilal Akil

@ 2unco ฉันดีใจที่คุณคิดออก if let a = a {}นี้จะอธิบายในส่วนสุดท้ายของคำตอบของฉันเกี่ยวกับ
tobiasdm

ฉันจะย้ายการเรียกร้องให้makeKeyAndVisible()จะเป็นหลังจากที่rootViewControllerการตั้งค่า มิฉะนั้นคุณจะได้รับคำเตือนเกี่ยวกับวิธีที่หน้าต่างคาดว่าจะมีตัวควบคุมมุมมองรูทเมื่อสิ้นสุดการเปิดแอปพลิเคชัน
Sebastien Martin

if let a = a { }ดูแปลก ๆ คุณแน่ใจหรือไม่ที่จะใช้ชื่อตัวแปรเดียวกันสำหรับการอ้างอิงแบบไม่บังคับ Apple มักใช้ชื่อที่แตกต่างกันในเอกสาร Swift นอกจากนี้ทำไมถึงดีกว่าการใช้window!ทุกครั้ง?
ma11hew28

1. if let a = a { }สมบูรณ์ดี คุณสามารถใช้if let anA = a { }ถ้ามันทำให้คุณรู้สึกสบายขึ้น 2. window!เป็นการตรวจสอบรันไทม์เนื่องจากคุณได้ทำการแกะอุปกรณ์เสริมอย่างชัดเจน ฉันชอบการตรวจสอบเวลาคอมไพล์ที่ Swift ให้เราดังนั้นทำไมไม่ใช้มัน
tobiasdm

13

หากคุณต้องการเริ่มต้น 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
}

6

ลองใช้รหัสต่อไปนี้:

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

ฉันพบคำตอบว่าไม่มีส่วนเกี่ยวข้องกับการตั้งค่า 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
    }

}

แต่ทำไมตอบคำถามของคุณเองถ้าคำตอบอยู่ในคำตอบอื่น?
akashivskyy

หน้าเว็บไม่ได้รับการอัปเดตและฉันไม่เห็นคำตอบหลังจากโพสต์เท่านั้น
EhTd

2

คุณสามารถทำได้ดังนี้:

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: UIWindow หรือไม่ ระบุว่าเป็นคุณสมบัติเสริม?
Sean Dunford

ฉันเพิ่งลองเพิ่ม var ตัวที่สองใน app delegate โดยไม่มีมันและพบว่าข้อความข้างต้นของฉันเป็นจริง
Sean Dunford

2

ฉันแนะนำให้คุณใช้คอนโทรลเลอร์และ xib

MyViewController.swift และ MyViewController.xib

(คุณสามารถสร้างผ่าน File-> New-> File-> Cocoa Touch Class และตั้งค่า "ยังสร้างไฟล์ XIB" จริงคลาสย่อยของ UIViewController)

class MyViewController: UIViewController {
   .....    
}

และAppDelegate.swift func applicationเขียนรหัสต่อไปนี้

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

น่าทำงาน!


ฉันลองแบบเดียวกับที่คุณพูดถึง แต่เกิดข้อผิดพลาด: การยุติแอปเนื่องจากข้อยกเว้นที่ไม่ถูกจับ 'NSInternalInconsistencyException' เหตุผล: 'ไม่สามารถโหลด NIB ในชุดรวม:
shripad20


2

อัปเดต: Swift 5 และ iOS 13:

  1. สร้างแอปพลิเคชัน Single View
  2. ลบMain.storyboard (คลิกขวาแล้วลบ)
  3. ลบStoryboard Nameจากการกำหนดค่าฉากเริ่มต้นใน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()
    }
}

1

นี่คือตัวอย่างการทดสอบที่สมบูรณ์สำหรับ 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

ทำไมคุณไม่สร้างแอปพลิเคชันเปล่า ๆ สตอรี่บอร์ดไม่ได้สร้างให้ฉัน ...


0

เราสามารถสร้างแอปพลิเคชันที่ใช้การนำทางโดยไม่มีสตอรี่บอร์ดใน 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 - ทำงานกับการควบคุม /


0

ใน iOS 13 ขึ้นไปเมื่อคุณสร้างโปรเจ็กต์ใหม่โดยไม่ใช้สตอรีบอร์ดให้ใช้ขั้นตอนด้านล่าง:

  1. สร้างโครงการโดยใช้ Xcode 11 ขึ้นไป

  2. ลบหัวปากกาสตอรีบอร์ดและชั้นเรียน

  3. เพิ่มไฟล์ใหม่ใหม่ด้วย xib

  4. ต้องตั้งค่ามุมมองรูทเป็น UINavigationController SceneDelegate

  5. เพิ่มฉากด้านล่างรหัส func (_ ฉาก: UIScene เซสชั่น willConnectTo: UISceneSession ตัวเลือก connectionOptions: UIScene.ConnectionOptions) {// ใช้วิธีนี้ในการเลือกการกำหนดค่าและแนบ UIWindow windowไป sceneUIWindowScene // หากใช้สตอรีบอร์ดwindowคุณสมบัติจะเริ่มต้นและแนบเข้ากับฉากโดยอัตโนมัติ // ผู้รับมอบสิทธิ์นี้ไม่ได้หมายความว่าฉากเชื่อมต่อหรือเซสชันเป็นของใหม่ (ดูapplication:configurationForConnectingSceneSessionแทน) // guard let _ = (ฉากเป็น? UIWindowScene) else {return}

    ถ้าให้ windowScene = ฉากเป็น? UIWindowScene {self.window = UIWindow (windowScene: windowScene) ให้ mainController = HomeViewController () เป็น HomeViewController ให้ navigationController = UINavigationController (rootViewController: mainController) self.window! .rootViewController = navigationController self.window! .makeKeyAndVisible ()}}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.