macOS Dev: NSTableView

实现一个 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)

demo

参考

  • 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

你可能感兴趣的:(macOS Dev: NSTableView)