2016-09-04 30 views
2

我試圖在不使用Interface Builder的情況下創建一個macOS應用程序。我的項目構建並運行,但我的主視圖控制器似乎沒有加載它的視圖。也就是說,viewDidLoad()方法不被調用。我正在使用Xcode-beta 8.0 beta 6(8S201h)。以編程方式在Swift中創建一個沒有XIB的NSViewController 3

NSViewController雨燕3文件說,這對view屬性:

如果這個屬性的值尚未設置,當你訪問它,視圖控制器調用loadView()方法。該方法依次設置視圖控制器的nibNamenibBundle屬性標識的筆尖文件的視圖。

如果您想直接設置視圖控制器的視圖,請在創建視圖控制器後立即設置此屬性的值。

而對於viewDidLoad

對於程序創建的視圖控制器,所述loadView()方法完成後此方法被立即調用。

最後,對於isViewLoaded

視圖控制器採用其視圖的延遲加載:一個視圖控制器被加載到存儲器中後,立即其isViewLoaded屬性的值是false。在loadView()方法返回並且在系統調用viewDidLoad()方法之前,值更改爲true

因此,文檔使我相信這是可能的。


我的項目是這樣的:

. 
├── main.swift 
└── Classes 
    ├── AppDelegate.swift 
    └── Controllers 
     └── PrimaryController.swift 

main.swift

import Cocoa 

let delegate = AppDelegate() 
NSApplication.shared().delegate = delegate 
NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) 

AppDelegate.swift

import Cocoa 

class AppDelegate: NSObject, NSApplicationDelegate { 
    func applicationDidFinishLaunching(_ aNotification: Notification) { 
     let pc = PrimaryController(nibName: nil, bundle: nil)! 
     print(pc.isViewLoaded) 
     pc.view = NSView() 
     print(pc.isViewLoaded) 
    } 
} 

PrimaryController.swift

import Cocoa 

class PrimaryController: NSViewController { 
    override func loadView() { 
     print("PrimaryController.loadView") 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     print("PrimaryController.viewDidLoad") 
    } 
} 

構建和運行一個項目,上述收益率這個控制檯輸出:

false 
true 

也就是說,鑑於負載的控制器,但loadViewviewDidLoad方法從不被調用。

我錯過了什麼?

回答

2

仔細閱讀文檔是有啓發性的。具體做法是:

當你訪問它,視圖控制器調用loadView()方法如果此屬性的值是尚未設置。

含義,loadView()當試圖讀取view財產前的屬性有值時纔會激活。直接爲屬性賦值會繞過方法調用。

所以,如果AppDelegate.applicationDidFinishLaunching(_:)是這樣寫的:

let pc = PrimaryController(nibName: nil, bundle: nil)! 
    print(pc.isViewLoaded) 
    let x = pc.view // accessing the view property before it has a value 
    print(pc.isViewLoaded) 

...然後loadView將被系統調用來嘗試加載的觀點:

false 
PrimaryController.loadView 
false 

注意viewDidLoad()仍不因爲沒有視圖可以自動與控制器關聯(即,筆尖nilPrimaryController.xib不存在)。完成該過程的正確方法是手動加載在PrimaryController.loadView()視圖:

print("PrimaryController.loadView") 
view = NSView() // instantiate and bind a view to the controller 

現在程序得到所需的結果:

false 
PrimaryController.loadView 
PrimaryController.viewDidLoad 
true 
0

最小設置,以使從代碼的ViewController(SWIFT 4.1)

class WelcomeViewController: NSViewController { 

    private lazy var contentView = MyCustomClassOrJustNSView() 

    override func loadView() { 
     view = contentView 
    } 

    init() { 
     super.init(nibName: nil, bundle: nil) 
    } 

    required init?(coder: NSCoder) { 
     fatalError() 
    } 
} 
相關問題