Làm cách nào để tạo một dự án Swift mới mà không cần sử dụng Storyboards?


107

Tạo một dự án mới trong XCode 6 không cho phép tắt Bảng phân cảnh. Bạn chỉ có thể chọn Swift hoặc Objective-C và sử dụng hoặc không sử dụng Core Data.

Tôi đã thử xóa bảng phân cảnh và từ dự án xóa bảng phân cảnh chính và thiết lập thủ công cửa sổ từ didFinishLaunching

Trong AppDelegate, tôi có cái này:

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

Tuy nhiên, XCode cho tôi một lỗi:

Lớp 'AppDelegate' không có trình khởi tạo

Bất cứ ai đã thành công trong việc này?


Câu trả lời:


71

Bạn phải đánh dấu các biến windowtestNavigationControllerlà tùy chọn:

var window : UIWindow?
var testNavigationController : UINavigationController?

Các lớp Swift yêu cầu các thuộc tính không tùy chọn được khởi tạo trong quá trình khởi tạo:

Các lớp và cấu trúc phải đặt tất cả các thuộc tính được lưu trữ của chúng thành một giá trị ban đầu thích hợp vào thời điểm một thể hiện của lớp hoặc cấu trúc đó được tạo. Thuộc tính đã lưu trữ không được để ở trạng thái không xác định.

Các thuộc tính của kiểu tùy chọn được khởi tạo tự động với giá trị là nil, cho biết rằng thuộc tính được cố ý sử dụng để “chưa có giá trị” trong quá trình khởi tạo.

Khi sử dụng các biến tùy chọn, hãy nhớ mở chúng ra !, chẳng hạn như:

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

1
Mọi thứ đều có ý nghĩa hoàn hảo trong câu trả lời của bạn, cho đến khi kết thúc. bạn sẽ vui lòng giải thích rằng phần cuối cùng ?? mở ra? cái này có bắt buộc không?
DanMoore

1
Bạn không thể lưu trữ một thuộc tính không phải tùy chọn trong của mình AppDelegate(trừ khi nó có một giá trị trong quá trình khởi tạo hoặc nó được giải quyết một cách lười biếng). Nếu bạn lưu trữ một thuộc tính tùy chọn và bạn chắc chắn rằng nó không phải nil, thì bạn "mở gói nó khỏi tùy chọn" bằng !toán tử.
akashivskyy

cách thực hành tốt nhất là gì, self.window! hoặc sử dụng if let window = ..?
laughingman

1
Nếu bạn chắc chắn rằng cửa sổ của bạn tồn tại (và bạn có thể chắc chắn trong trường hợp cụ thể này), bạn có thể sử dụng !.
akashivskyy

vậy điều này có nghĩa là khi chúng ta sử dụng bảng phân cảnh, màu nền mà nó được mặc định bằng cách nào đó .white?
Honey,

91

Tất cả những gì cần thiết để không sử dụng Bảng phân cảnh cho rootViewController:

1 · Thay đổi AppDelegate.swiftthành:

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 · Tạo một ViewControllerlớp con của UIViewController:

import UIKit

class ViewController: UIViewController {

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

3 · Nếu bạn đã tạo dự án từ mẫu Xcode:

  1. Xóa cặp khóa-giá trị cho khóa "Main storyboard file base name"từ Info.plist.
  2. Xóa tệp bảng phân cảnh Main.storyboard.

Như bạn có thể thấy trong đoạn mã đầu tiên, thay vì hoàn toàn mở gói một tùy chọn, tôi thích if letcú pháp để mở gói thuộc tính tùy chọn window. Ở đây tôi đang sử dụng nó giống như if let a = a { }để tùy chọn atrở thành một tham chiếu không tùy chọn bên trong if-statement có cùng tên - a.

Cuối cùng self.là không cần thiết khi tham chiếu đến thuộc windowtính bên trong lớp riêng của nó.


1
Tại sao if let window = window {? Tôi đã hiểu rồi! Nó để bạn không cần phải sử dụng window!mọi lúc.
Bilal Akil,

@ 2unco Tôi rất vui vì bạn đã tìm ra nó. Điều này được mô tả trong phần cuối cùng của câu trả lời của tôi về if let a = a {}.
tobiasdm

Tôi sẽ di chuyển các cuộc gọi đến makeKeyAndVisible()sau khi thiết lập rootViewController. Nếu không, bạn sẽ nhận được cảnh báo về cách cửa sổ dự kiến ​​có bộ điều khiển chế độ xem gốc khi kết thúc khởi chạy ứng dụng.
Sebastien Martin

if let a = a { }trông kỳ lạ. Bạn có chắc là có thể sử dụng cùng một tên biến cho tham chiếu không tùy chọn không? Apple luôn sử dụng các tên khác nhau trong tài liệu Swift của họ. Ngoài ra, tại sao điều này tốt hơn là chỉ sử dụng window!mọi lúc?
ma11hew28

1. if let a = a { }là hoàn toàn tốt. Bạn có thể sử dụng if let anA = a { }nếu cảm thấy thoải mái hơn. 2. window!là một kiểm tra thời gian chạy vì bạn mở gói một cách rõ ràng một tùy chọn. Tôi thích kiểm tra thời gian biên dịch mà Swift cung cấp cho chúng tôi, vậy tại sao không sử dụng nó.
tobiasdm

13

Nếu bạn muốn Khởi tạo viewController của mình bằng xib và cần sử dụng bộ điều khiển điều hướng. Đây là một đoạn mã.

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

Hãy thử mã sau:

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

Tôi đã tìm thấy câu trả lời rằng nó không liên quan gì đến thiết lập xcode, xóa bảng phân cảnh và tham chiếu khỏi dự án là điều đúng đắn. Nó liên quan đến cú pháp nhanh chóng.

Mã như sau:

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
    }

}

Nhưng tại sao phải trả lời câu hỏi của chính bạn, nếu giải pháp nằm trong một câu trả lời khác?
akashivskyy

trang không được cập nhật và tôi không thấy câu trả lời, chỉ sau khi đăng
EhTd

2

Bạn chỉ có thể làm như thế này:

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

Có cửa sổ var: UIWindow không? chỉ định rằng đó là một thuộc tính tùy chọn?
Sean Dunford

Tôi vừa thử thêm var thứ hai trong ứng dụng ủy quyền mà không có nó và nhận thấy tuyên bố ở trên của tôi là đúng.
Sean Dunford

2

Tôi khuyên bạn nên sử dụng bộ điều khiển và xib

MyViewController.swiftMyViewController.xib

(Bạn có thể tạo thông qua File-> New-> File-> Cocoa Touch Class và đặt "cũng tạo tệp XIB" true, lớp con của UIViewController)

class MyViewController: UIViewController {
   .....    
}

AppDelegate.swift func applicationViết đoạn mã sau

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

Nó phải là công việc!


Tôi cố gắng giống như cách bạn nói nhưng lỗi: Chấm dứt ứng dụng do ngoại lệ còn tự do 'NSInternalInconsistencyException', lý do: 'Không thể tải NIB trong bó:
shripad20

2

Cập nhật cho Swift 3.0:

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

2

Cập nhật: Swift 5 và iOS 13:

  1. Tạo một Ứng dụng Xem một lần.
  2. Xóa Main.storyboard (nhấp chuột phải và xóa).
  3. Xóa Tên bảng phân cảnh khỏi cấu hình cảnh mặc định trong Info.plisttệp:nhập mô tả hình ảnh ở đây
  4. Mở SceneDelegate.swiftvà thay đổi func scenetừ:
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 }
}

đến

 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

Đây là một ví dụ kiểm tra nhanh hoàn chỉnh cho một 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

Tại sao bạn không tạo một ứng dụng trống? bảng phân cảnh không được tạo cho tôi ...


0

Chúng tôi có thể tạo ứng dụng dựa trên điều hướng mà không có bảng phân cảnh trong Xcode 6 (iOS 8) như sau:

  • Tạo một ứng dụng trống bằng cách chọn ngôn ngữ dự án là Swift.

  • Thêm các tệp lớp cảm ứng ca cao mới với giao diện xib. (ví dụ: TestViewController)

  • Trong thời gian nhanh chóng, chúng tôi chỉ có một tệp tương tác với tệp xib tức là * .swift, không có tệp .h và .m.

  • Chúng tôi có thể kết nối các điều khiển của xib với tệp nhanh chóng giống như trong iOS 7.

Sau đây là một số đoạn mã để làm việc với các điều khiển và 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()
    }

}

Các thay đổi trong tệp 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) {
    }

}

Tìm mẫu mã và thông tin khác trên http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and -work-with-control /


0

Trong iOS 13 trở lên khi bạn tạo dự án mới mà không có bảng phân cảnh, hãy sử dụng các bước dưới đây:

  1. Tạo dự án bằng Xcode 11 trở lên

  2. Xóa ngòi và lớp bảng phân cảnh

  3. Thêm tệp mới mới với xib

  4. Cần đặt chế độ xem gốc là UINavigationController SceneDelegate

  5. thêm cảnh func bên dưới (_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {// Sử dụng phương pháp này để tùy chọn cấu hình và đính kèm UIWindow windowvào UIWindowScene được cung cấp scene. // Nếu sử dụng bảng phân cảnh, thuộc windowtính sẽ tự động được khởi tạo và gắn vào cảnh. // Đại biểu này không ngụ ý cảnh hoặc phiên kết nối là mới (xem application:configurationForConnectingSceneSessionthay thế). // Guard let _ = (scene as? UIWindowScene) else {return}

    nếu để windowScene = cảnh như? UIWindowScene {self.window = UIWindow (windowScene: windowScene) let mainController = HomeViewController () as HomeViewController let navigationController = UINavigationController (rootViewController: mainController) self.window! .RootViewController = navigationController self.ey}}.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.