在Swift 3中以编程方式创建一个没有XIB的NSViewController [英] Programmatically create an NSViewController without an XIB in Swift 3

查看:168
本文介绍了在Swift 3中以编程方式创建一个没有XIB的NSViewController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在不使用Interface Builder的情况下制作macOS应用.我的项目已构建并运行,但是主视图控制器似乎并未加载其视图.即,不会调用viewDidLoad()方法.我正在使用Xcode-beta 8.0 beta 6(8S201h).

I'm trying to make a macOS app without using Interface Builder. My project builds and runs, but my primary view controller doesn't seem to be loading its view. That is, the viewDidLoad() method is not invoked. I'm using Xcode-beta 8.0 beta 6 (8S201h).

NSViewController的Swift 3文档对此内容进行了说明:

The Swift 3 documentation for NSViewController says this about the view property:

如果在访问该属性时未设置其值,则视图控制器将调用loadView()方法.相应地,该方法从视图控制器的nibNamenibBundle属性标识的nib文件中设置视图.

If this property’s value is not already set when you access it, the view controller invokes the loadView() method. That method, in turn, sets the view from the nib file identified by the view controller’s nibName and nibBundle properties.

如果您想直接设置视图控制器的视图,请在创建视图控制器后立即设置此属性的值.

If you want to set a view controller’s view directly, set this property’s value immediately after creating the view controller.

对于viewDidLoad:

对于以编程方式创建的视图控制器,在loadView()方法完成后立即调用此方法.

For a view controller created programmatically, this method is called immediately after the loadView() method completes.

最后,对于isViewLoaded:

视图控制器采用延迟加载其视图:将视图控制器加载到内存后,其isViewLoaded属性的值立即为false.在loadView()方法返回之后且恰好在系统调用viewDidLoad()方法之前,该值将更改为true.

A view controller employs lazy loading of its view: Immediately after a view controller is loaded into memory, the value of its isViewLoaded property is false. The value changes to true after the loadView() method returns and just before the system calls the viewDidLoad() method.

因此文档使我相信这是可能的.

So the documentation leads me to believe it is possible.

我的项目如下:

 .
 ├── 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")
    }
}

使用上述内容构建和运行项目会产生以下控制台输出:

Building and running a project with the above yields this console output:

false
true

也就是说,视图将为控制器加载,但不会调用loadViewviewDidLoad方法.

That is, the view loads for the controller, but the loadView and viewDidLoad methods are never invoked.

我想念什么?

推荐答案

仔细阅读该文档对我们很有启发.具体来说:

A careful reading of the documentation is enlightening. Specifically:

如果访问时尚未设置此属性的值,则视图控制器将调用loadView()方法.

If this property’s value is not already set when you access it, the view controller invokes the loadView() method.

意思是,仅当尝试读取view属性之前具有值时,才调用loadView().直接为属性分配值将绕过方法调用.

Meaning, loadView() is only invoked when an attempt is made to read the view property before the property has a value. Assigning a value to the property directly will bypass the method call.

因此,如果AppDelegate.applicationDidFinishLaunching(_:)是这样写的:

So if AppDelegate.applicationDidFinishLaunching(_:) is written like this:

    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将被系统调用以尝试加载视图:

...then loadView will be invoked by the system to attempt to load the view:

false
PrimaryController.loadView
false

请注意,由于无法自动将视图与控制器关联(即笔尖为nilPrimaryController.xib不存在),因此仍未调用viewDidLoad().完成此过程的正确方法是在PrimaryController.loadView()中手动加载视图:

Note that viewDidLoad() is still not invoked, since no view can be automatically associated with the controller (ie, the nib is nil and PrimaryController.xib doesn't exist). The correct way to complete the process is to manually load the view in PrimaryController.loadView():

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

现在程序会提供所需的结果:

Now the program gives the desired result:

false
PrimaryController.loadView
PrimaryController.viewDidLoad
true

这篇关于在Swift 3中以编程方式创建一个没有XIB的NSViewController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆