实现一个 NSTableView,NSTableCellVIew 根据内容量和 window 宽度自动适应高度。
NSTableView 和 UITableView 有很大不同。比如 iOS 在设置好 autolayout 之后就不用去管 cell 的高度了。但是 macOS 中仍然需要提供高度数据。其他诸如点击事件,响应 cell 的背景色等等 api 也和 iOS 不一样。由于 window 的大小可变,渲染图形的时候要考虑到这种情况,不能依赖 autolayout 一劳永逸。总之, macOS 要考虑的情况多一些,能找到的资料又相对欠缺。
NSTableView
Storyboard 中往 ViewController 拖入 NSTableView 控件,设置 autolayout 填满视图
中栏层级结构图中右键拖放 Table View 至 View Controller,连接 NSTableViewDelegate 和 NSTableViewDataSource
拖一个 tableView 的 IBOutlet 引用至 ViewController
-
注册 Cell
@IBOutlet weak var tableView: NSTableView!{ didSet{ let nib = NSNib(nibNamed: "CustomCell", bundle: nil) self.tableView.register(nib, forIdentifier: "CustomCell") } }
让 Cell 填满视图宽度
- 选择 table view 后,Attributes inspector 中设置 Columns: 1,去掉 Headers, Reordering, Resizing 选项,Column Sizing: Uniform
- 如果显示不正确,把 table view 拉到比两个 columns 还小的宽度,然后再拉回与 window 宽度同宽
NSTableCellView
- 新建 CustomCell.swift
- 新建 macOS > User Interface > Empty > CustomCell.xib,拖入 NSTableCellView,拖入一个 Custom View 作为 contentView,之后所有的空间都放在这个 contentView 上,稍后将用这个 contentView 来获得 cell 的高度
- Attribute Inspector 中设置 CustomCell.xib 的类为 CustomCell,identifier > CustomCell,拖 IBOutlet 至 CustomCell.swift
把值显示到 cell 的两种方式
1. 绑定 Object
- 选择 Table Cell View,Bindings inspector > value > Bind to: Table Cell View,Model Key Path: objectValue
2. 给 NSTableCellView 实例赋值
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = tableView.make(withIdentifier: "CustomCell", owner: self) as! CustomCell
let item = dataSource?[row]
cell.setContent(item: item)
return cell
}
动态高度
通过容器视图的 fittingSize 方法获得高度
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
let cell = tableView.make(withIdentifier: "CustomCell", owner: self) as! CustomCell
let item = dataSource?[row]
cell.setContent(item: item)
return cell.contentView.fittingSize.height
}
收取窗口改变的通知,在 window 大小改变的时候 reloadData()。
NotificationCenter.default.addObserver(self, selector: #selector(receivedNotification(notification:)), name: NSNotification.Name.NSWindowDidResize, object: nil)
参考
- https://developer.apple.com/reference/appkit/nstableview
- http://stackoverflow.com/questions/7545490/how-can-i-have-the-only-column-of-my-nstableview-take-all-the-width-of-the-table
- https://www.youtube.com/watch?v=b6jQCLLPJ_8
- https://www.youtube.com/watch?v=iJHskQ27gVM
- https://ez-net.jp/article/00/jVzOXcdJ/C603m85YfWFm/
- http://sxiaojian.com/2015/08/11/Mac-NSTableView/
- http://stackoverflow.com/questions/22263603/how-to-get-the-height-of-an-nstablecellview-that-uses-autolayout