NSViewController
视图控制器和窗口控制器一样,是一类非常重要的控制器,它负责管理视图的生命周期过程,同时管理子视图控制器,实现了不同视图控制器之间的界面切换控制接口。
- NSViewController是用来管理view视图的控制器,可以基于xib/storyboard文件来加载通过Xcode设计好的界面视图。
- NSViewcCortoller不能独立显示,必须将NSViewController的view做为NSWindow的子视图(内容视图)或者做为NSWindowController的contentViewController才能显示。
- NSViewController负责视图生命周期过程管理;可做为控制器容器管理多个子视图控制器;提供或实现了不同视图控制器之间跳转方式接口。
View的生命周期
每个阶段方法如下:
-
- 加载
NSViewController的核心属性为view
,任何时候访问view时,如果view值为空,则触发加载过程loadView方法从xib/storyboard文件去加载,然后执行viewDidLoad方法表示界面加载完成。
- 加载
func loadView()
func viewDidLoad()
-
- 显示/隐藏
view开始显示出来之前执行viewWillAppear方法,接下来会执行布局相关方法,最后界面完全显示出来,执行viewDidAppear,整个过程就完成。视图关闭的流程很简单,依次执行viewWillDisappear和viewDidDisappear方法。
- 显示/隐藏
func viewWillAppear()
func viewDidAppear()
func viewWillDisappear()
func viewDidDisappear()
-
- 布局
func updateViewConstraints()
func viewWillLayout()
func viewDidLayout()
添加了一个控件并设置约束后,NSViewController完整的方法执行顺序
func loadView()
func viewDidLoad()
func viewWillAppear()
func updateViewConstraints()
func viewWillLayout()
func viewDidLayout()
func viewDidAppear()
func viewWillLayout()
func viewDidLayout()
注意:
NSView执行updateConstraints方法时,如果view存在一个Controller,则会执行Controller的updateViewConstraints方法。一般情况下不应该在NSView的updateConstraints方法中放置约束,主要的原因是自动布局约束是多个视图之间的关系,集中放置便于理解和管理。所以NSViewController的updateViewConstraints方法是放置界面上元素之间约束的最佳场所。NSView的updateConstraints的方法仅仅在子视图内部管理各个subview时,或者需要频繁执行需要提升性能的时候才需要进行override重写。
ViewController的三种创建方式
-
- 使用Xib方式创建
// NSViewController有个nibName属性
open var nibName: NSNib.Name? { get }
loadView
方法在OSX 10.9
系统之前,如果NSViewController的nibName为空则返回nil。
OSX 10.10及以后
的系统对loadView
方法做了优化,如果nibName为空,自动去加载名字跟controller一样的nib文件
,这样大多数情况下都可以按第一种方法去创建NSViewController了。默认创建的controller的nib文件都是跟类名一致的。
let myViewController = MyViewController.init()
let myViewController = NSViewController.init(nibName: "MyViewController", bundle: nil)
-
- 使用Storyboard方式创建
创建一个名为Storyboard的Storyboard文件,拖放一个View Controller到xib文件导航区。点击View Controller节点,右边属性面板中Storyboard ID输入myVC。
let storyboard = NSStoryboard.init(name: "Storyboard", bundle: nil)
let myViewController = storyboard.instantiateController(withIdentifier: "myVC")
-
- 代码直接创建
let viewController = NSViewController.init()
viewController.view = NSView.init(frame: NSRect.init(x: 0, y: 0, width: 200, height: 200))
另外一种方式是直接在NSViewController的loadView
中设置创建View
override func loadView() {
self.view = NSView.init(frame: NSRect.init(x: 0, y: 0, width: 200, height: 200))
}
representedObject属性
NSViewController存在一个id类型的representedObject
属性对象。它可以用来存储NSViewController的模型对象
。
视图间切换
OS X10.10之后
提供了多种视图控制器之间的切换方法如下:
open func present(_ viewController: NSViewController, animator: NSViewControllerPresentationAnimator)
open func presentAsSheet(_ viewController: NSViewController)
open func presentAsModalWindow(_ viewController: NSViewController)
open func present(_ viewController: NSViewController, asPopoverRelativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge, behavior: NSPopover.Behavior)
@IBAction open func dismiss(_ sender: Any?)
open func dismiss(_ viewController: NSViewController)