前言
几乎每一个程序都有窗口界面,了解窗口及相关对象的概念非常重要,开发窗口界面和窗口内的视图元素大概有三种方式。
- StoryBoard
- XIB
- 手写代码
本文主要介绍使用StoryBoard来创建和管理窗口。
创建项目
勾选StoryBoard和Swift,命名为:02.Window
打开: Main.storyboard 文件,该文件是StoryBoard设计文件,就在这里管理窗口和窗口内的视图
几个关键对象
看到Main.storyboard里的内容你可能有点迷惑,刚开始我也是的,先介绍几个关键对象和之间的关系 有助于你理解使用StoryBoard。
关于NS前缀
你会发现在Mac平台上很多类的前缀都是NS,那么NS代表什么意思呢?其实是历史原因,乔布斯被迫离开苹果公司后创立了NeXT公司,而回归苹果后发布的第一个操作系统叫做:NeXTSTEP,后面慢慢衍生到Mac系统中,将代码合并时,由于很多基础代码来自NeXTSTEP,所以这些类取其前缀NeXTSTEP,以标识来自NeXTSTEP操作系统。
NSWindow
顾名思义,NS是前缀,Window是窗口,就是你所看到的一个窗口的对象。他只是一个窗口容器,展示的内容需要有window里面的View来提供,也就是下面的NSView。
By the way, Swift是面向对象的编程语言,心中要牢记,万物皆对象。
NSWindow还负责接受用户的鼠标、键盘等系统事件。
窗口对象分为键盘窗口(Key Window)和主窗口(Main Window)
- 键盘窗口就是可以接受用户的键盘、鼠标、触控板事件的窗口
- 主窗口就是活动窗口,一般为获取焦点的窗口
同一时刻只能有一个键盘窗口和一个主窗口,键盘窗口和一个主窗口可以为同一个窗口
NSWindowController
窗口控制器,用来管理window的控制器。能够管理并从xib或storyboard文件中加载的窗口视图,以及管理不同场景多个界面窗口的切换
NSWindowController 与 NSWindowController的关系
一个NSWindow 可能有也可能没有 NSWindowController,如果没有NSWindowController 该窗口关闭后系统可能会自动释放该窗口。
NSWindowController一般都会有一个NSWindow对象(或从contentViewController中获取window对象。)
NSView
视图对象,大多UI组件都是它的子类。你所看到的几乎所有东西都是View,NSWindow里展示的内容就是这个对象,你可以控制这个对象的大小、位置、样式甚至动画,来实现你想要的效果。
NSView是有层级的,你可以这么理解,最开始有一个NSView对象,把他理解为是一幅画的最初形态:一张白纸,然后你可能在里面画一个圆圈,这个圆圈又是一个NSView,画一个鸡蛋,又是一个NSView对象,圆圈和鸡蛋都属于这张白纸的子View(SubView), 鸡蛋里面可能会有一些轮廓,或者印上一些字(有些蛋的确会印字的)这些轮廓或字又都是NSView,它们是鸡蛋的子View(SubViews)。甚至,你在画上的每一笔都是一个子View。各种子View的绘制,就能造就一幅优美壮丽的画了。
NSViewController
视图控制器和窗口控制器类似,它主要负责管理视图的生命周期,同时管理子视图控制器,实现了不同视图控制器之间的界面切换控制。
一般每个页面都会有一个NSViewController自定义类来负责改页面的事件和业务逻辑处理,从xib/Storyboard中加载设计好的页面。
NSViewController必须有一个view 或者有contentViewController。
NSWindow 与 NSView 的关系
- 每一个窗口都依赖视图而存在,窗口必须有一个根视图才能展示,即内容视图。
- 每个视图都必须存在一个窗口中,通过self.view.window获取view的window。
NSWindow对象加载之前,即windowDidLoad执行时会先加载window对应的内容视图从而触发视图控制器的viewDidLoad方法,在viewDidLoad方法中窗口还没初始化完,所以无法获取到窗口,因此要在viewDidAppear方法中才能获取到。
NSWindowController 与 NSViewController的关系
NSWindowController和NSWindow之间是互为引用的关系。
NSWindow的内容视图contentView为NSView。 当NSWindowController配置了contentViewController时,那这个contentViewController下的view最终就是该NSWindowController下的window的contentView。
而view所在的window就是该NSWindowController下的window。下面有个关系图:
关于刚刚新建的StoryBoard
为窗口对象、视图对象、窗口控制器、视图控制器添加自定义类型
如果你想控制窗口或视图,添加事件处理,就需要重写对应的类,在StoryBoard中将指定的对应的类型。
创建先创建几个类型:
- 创建名称为:MyNSView的Cocoa class,继承NSView
- 创建名称为:NSWindow的Cocoa class,继承NSWindow
- 创建名称为:MyWindowController class,继承NSWindowController ViewController不需要创建,默认有了。
将这几个类在StoryBoard中设置
视图控制器的生命周期
修改ViewController中的代码,添加日志打印:
import Cocoa
class ViewController: NSViewController {
override func loadView() {
super.loadView()
print("loadView")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("viewDidLoad")
}
override func viewWillAppear() {
super.viewWillAppear()
print("viewWillAppear")
}
override func viewWillDisappear() {
super.viewWillDisappear()
print("viewWillDisappear")
}
override func viewDidAppear() {
super.viewWillDisappear()
print("viewDidAppear")
}
override func viewDidDisappear() {
super.viewDidDisappear()
print("viewDidDisappear")
}
override func updateViewConstraints() {
super.updateViewConstraints()
print("updateViewConstraints")
}
override func viewWillLayout() {
super.viewWillLayout()
print("viewWillLayout")
}
override func viewDidLayout() {
super.viewDidLayout()
print("viewDidLayout")
}
}
启动程序,查看打印为:
loadView
viewDidLoad
viewWillAppear
updateViewConstraints
viewWillLayout
viewDidLayout
viewDidAppear
窗口跳转
添加一个新的窗口控制器,实现页面跳转。
先在默认窗口中添加一个button,打开StoryBoard,选中NSView,按住快捷键:Command+Shift+L,输入:button,选择:Push Button. 按住拖动到窗口中,双击修改button文字为:页面跳转
再按住,Command+Option+Control+回车,打开 代码和设计 关联页面,按住Ctrl+拖动button按钮到代码中,新增一个事件方法为:tapButtonAction
选择Action,Name为:tapButtonAction,点击connect。 这样就添加好了事件函数,按钮点击时就会触发该函数
再拖动一个outlet,ctrl+鼠标拖动到ViewController类的上边部分,选择:outlet
再回到StoryBoard中,按右上角的加号(Command+Shift+L),输入:windowController, 拖动到Storyboard中,选中新增的windowController,打开右侧面板,在StoryBoard ID一栏填入:MyNewWindow。
在刚刚创建的新的窗口中拖入一个Wrapping label,双击修改内容为:Hello, This's New!
然后回到刚刚的按钮点击事件函数中,添加如下代码:
@IBAction func tapButtonAction(_ sender: Any) {
button.title = "已跳转"
let windowController = storyboard?.instantiateController(withIdentifier: "MyNewWindow") as? NSWindowController
windowController?.showWindow(self)
}
启动项目,之后点击按钮就可以跳转新页面了
最后
这就是今天的所有内容,介绍了StoryBoard中设计的主要对象,和几个对象之间的关系,如何将页面事件与代码做关联,如何跳转页面(最基础),下节介绍在Cocoa上面几种页面跳转方式。