Mac开发 NSTableView(代码详解)

转载请联系作者获取授权,并标明文章作者,谢谢!

一、前言

本文所有代码基于Xcode8.3.3,Swift3.0开发。
NSTableView是macOS开发中很重要的控件,用于滚动数据,表格数据等复杂视图的实现。首先如果想要实现NSTableView的滚动效果需要将它承载在一个NSScrollView里。和iOS中的UITableView类似数据源也是DataSource,视图属性也是由Delegate控制。

在OS X v10.6版本之前,NSTableView中行数据载体视图必须是NSCell的子类,之后版本的OS X支持开发者创建基于View的TableView视图,同样也支持基于Cell的TabelView视图,在开发者,我们可以根据实际需求选择。

二、构建一个简单的NSTableView视图

创建一个WindowVC在里面构建NSTableView。
关于NSWindowController的简述和创建请看这篇文章:NSWindowController

    private lazy var tableView: NSTableView = {
        let tmpTableView = NSTableView()
        tmpTableView.delegate = self
        tmpTableView.dataSource = self
        tmpTableView.allowsColumnSelection = true
        return tmpTableView
    }()
    
    var dataSource = Array<Any>()
override func windowDidLoad() {
        super.windowDidLoad()
        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
        //初始化数据源
        for i in 0..<10{
            let dataStr = "第\(i+1)条数据"
            dataSource.append(dataStr)
        }
        //初始化ScrollView用于承载tableView附有滚动效果
        let scrollView = NSScrollView()
        scrollView.hasVerticalScroller = true
        scrollView.frame = CGRect.zero
        self.window?.contentView?.addSubview(scrollView)
        scrollView.snp.makeConstraints { (make) in
            make.edges.equalTo(0)
        }
        //初始化两个column
        let column1 = NSTableColumn(identifier: "test1")
        column1.width = 200
        column1.minWidth = 200
        column1.maxWidth = 201
        column1.title = "column1"
        let column2 = NSTableColumn(identifier: "test2")
        column2.width = 200
        column2.minWidth = 200
        column2.maxWidth = 201
        column2.title = "column2"
        column2.isEditable = true
        column2.headerToolTip = "提示"
        column2.isHidden = false
        column2.sortDescriptorPrototype = NSSortDescriptor(key: "sortDescriptorPrototyp", ascending: false)
        //允许自动调整Column的尺寸
        column1.resizingMask = NSTableColumnResizingOptions.autoresizingMask
        column2.resizingMask = NSTableColumnResizingOptions.autoresizingMask
        tableView.frame = CGRect.zero
        tableView.addTableColumn(column1)
        tableView.addTableColumn(column2)
        scrollView.contentView.documentView = tableView
        tableView.snp.makeConstraints { (make) in
            make.top.left.right.equalTo(0)
        }
        
    }

下面是代理方法的实现:

    func numberOfRows(in tableView: NSTableView) -> Int {
        return 10
    }
    
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        return 40
    }
    
    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        var rowStr = ""
        if tableColumn?.identifier == "test1" {
            rowStr += "第1列,"
        }else if tableColumn?.identifier == "test2" {
            rowStr += "第2列,"
        }
        rowStr += (dataSource[row] as! String)
        return rowStr
    }
    
    func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
        print("oldDescriptors[0] -> (sortDescriptorPrototyp, descending, compare:)")
    }

工程运行效果如下图:

Cell-Base工程运行效果

我们来分析一下这个tableView的实现:这是一个典型的基于Cell-Base的NSTableView,数据核心代码是<code>objectValueFor tableColumn:</code>方法,和UITableView一样需要实现<code>numberOfRows,heightOfRow</code>方法,在<code>objectValueFor tableColumn:</code>方法中我们可以通过<code>tableColumn?.identifier</code>来指定我们之前添加的NSColumn从而可以确定每一列的每一行数据。

三、关于NSColumn

NSColumn可以理解为NSTableView的一列,我们可以给某一列设置一些属性(宽度,标题,编辑状态...等)。下面列举NSColumn的常用属性。

//初始化方法,指定一个列ID
public init(identifier: String)
//与此列关联的ID
open var identifier: String
//关联的TableView
unowned(unsafe) open var tableView: NSTableView?
//设置列宽度
open var width: CGFloat
//设置最小列宽度
open var minWidth: CGFloat
//设置最大列宽度
open var maxWidth: CGFloat
//设置类标题
open var title: String
/*
列标题视图 开发者可以对其进行修改
需要注意,NSTableHeaderCell是继承自NSTextFieldCell
*/
open var headerCell: NSTableHeaderCell
//设置此列是否可以进行编辑
open var isEditable: Bool
//进行列尺寸的调整 以列标题视图的宽度为标准 
open func sizeToFit()
//提供了这个属性,会在列标题那里显示一个排序按钮 点击列标题后可以进行排序操作(会回调相关协议方法)
@NSCopying open var sortDescriptorPrototype: NSSortDescriptor?
//设置列尺寸的调整模式 枚举如下
/*
public struct NSTableColumnResizingOptions : OptionSet {
    public init(rawValue: UInt)
    public static var autoresizingMask: NSTableColumnResizingOptions { get } //使用tableView的column调整策略
    public static var userResizingMask: NSTableColumnResizingOptions { get }//允许用户进行尺寸调整
}
*/
open var resizingMask: NSTableColumnResizingOptions
//设置列头的提示标题 当鼠标悬停在类标题上时  会显示此提示
open var headerToolTip: String?;
//设置此列是否隐藏
open var isHidden: Bool
//设置此列所有行的数据载体视图 如果不设置 默认为NSTextFieldCell
open var dataCell: Any
//为TableView列表提供数据载体视图
open func dataCell(forRow row: Int) -> Any

四、Cell-Base:基于Cell的NSTableView

Cell-Base的NSTableView是macOS早起开发的主要结构,其每一个载体都必须是基于NSCell或者其子类,必须实现<code> numberOfRows </code>和<code>objectValueFor tableColumn</code>两个方法。第一个方法设置行数,第二个给每个Cell载体赋予数据。需要注意,如果只实现这两个方法,则NSTableView会自动从列对象NSTableColume中取具体的行视图,通过dataCellForRow方法。

当<code>objectValueForTableColum </code>方法将每个行具体的数据返回后,编辑时会调用cell的<code>setObjectValue</code>方法(因此如果要自定义cell,必须实现这个方法)。如果我们要对Cell的渲染进行一些定制,可以在如下方法中实现:

//cell-base的cell展示前调用 可以进行自定制
    func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int) {
        let tmpCell = cell as! NSTextFieldCell
        tmpCell.textColor = NSColor.red
    }

实现下面的方法可以返回一个自定义的Cell,如果实现了这个方法,则TableView不会再从NSTableColumn对象中拿Cell实例。

//自定义cell
    func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell? {
        if tableColumn != nil{
            let cell = MyCell()
            return cell
        }
        return nil
    }

全部代码如下:(NSTalbeView和NSScrollView的创建以及属性和上方示例1代码一样,故下方只列举代理方法)

    //设置行数 通用
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 10
    }
    //设置行高度 通用
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        return 40
    }
    //绑定数据源
    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        var rowStr = ""
        if tableColumn?.identifier == "test1" {
            rowStr += "第1列,"
        }else if tableColumn?.identifier == "test2" {
            rowStr += "第2列,"
        }
        rowStr += (dataSource[row] as! String)
        return rowStr
    }
    //排序回调函数
    func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
        print("oldDescriptors[0] -> (sortDescriptorPrototyp, descending, compare:)")
    }
    //cell-base的cell展示前调用 可以进行自定制
    func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int) {
        let tmpCell = cell as! NSTextFieldCell
        tmpCell.textColor = NSColor.red
    }
    //设置是否可以进行编辑
    func tableView(_ tableView: NSTableView, shouldEdit tableColumn: NSTableColumn?, row: Int) -> Bool {
        if tableColumn?.identifier == "test1" {
            return true
        }
        return false
    }
    //用户编辑列表
    func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int) {
        print("\(object as! String)")
        dataSource[row] = object as! String
    }
    //设置鼠标悬停在cell上显示的提示文本
    func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String {
        if tableColumn?.identifier == "test2" {
            return dataSource[row] as! String
        }
        return ""
    }
    //当列表长度无法展示完整某行数据时 当鼠标悬停在此行上 是否扩展显示
    func tableView(_ tableView: NSTableView, shouldShowCellExpansionFor tableColumn: NSTableColumn?, row: Int) -> Bool {
        return true
    }
    //设置cell的交互能力
    /*
     如果返回YES,则Cell的交互能力会变强,例如NSButtonCell的点击将会调用- (void)tableView:(NSTableView *)tableView setObjectValue方法
     */
    func tableView(_ tableView: NSTableView, shouldTrackCell cell: NSCell, for tableColumn: NSTableColumn?, row: Int) -> Bool {
        return true
    }
    //自定义cell
    func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell? {
        if tableColumn != nil{
            let cell = MyCell()
            return cell
        }
        return nil
    }

五、View-Base:基于View的NSTableView

基于View-Base的NSTableView则要更加灵活,它可以是任意NSView的子类来作为NSTableView的载体,书写方式,自定义方式等更加简单易用,示例代码:

   //设置行数 通用
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 10
    }
    //设置行高度 通用
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        return 40
    }
    //View-base
    //设置某个元素的具体视图
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        
        let key = tableColumn?.identifier
        //根据ID取视图
        var view = tableView.make(withIdentifier: "cellId", owner: self)
        if (view==nil) {
            view = NSTextField()
            (view as! NSTextField).isBordered=false
            (view as! NSTextField).isEditable=false
            (view as! NSTextField).backgroundColor = NSColor.clear
            (view as! NSTextField).identifier = "cellId";
        }
        (view as! NSTextField).stringValue = "Identifier为:\(key!)列的数据,\(dataSource[row])"
        return view;
    }
    //设置每行容器视图
    func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
        let tableRowView = TableRow()
        let lineView = NSView()
        lineView.wantsLayer = true
        lineView.layer?.backgroundColor = NSColor.blue.cgColor
        tableRowView.addSubview(lineView)
        lineView.snp.makeConstraints { (make) in
            make.left.right.bottom.equalTo(0)
            make.height.equalTo(1)
        }
        return tableRowView
    }
    //当添加行时调用的回调
    func tableView(_ tableView: NSTableView, didAdd rowView: NSTableRowView, forRow row: Int) {
        print("addRow")
    }
    //当移除行时调用的回调
    func tableView(_ tableView: NSTableView, didRemove rowView: NSTableRowView, forRow row: Int) {
        print("removeRow")
    }

下面是运行效果:

View-Base工程运行效果

上面代码中用到了TableRow类,其实它是一个自定义的继承自NSTableRowView的类,实现如下:

import Cocoa

class TableRow: NSTableRowView {
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    //绘制选中状态的背景
    override func drawSelection(in dirtyRect: NSRect) {
        let selectionRect = NSInsetRect(self.bounds, 5.0, 5.0)
        NSColor.init(calibratedWhite: 72, alpha: 0.6).setStroke()
        NSColor.init(calibratedWhite: 82, alpha: 0.6).setFill()
        let selectionPath = NSBezierPath.init(roundedRect: selectionRect, xRadius: 10, yRadius: 10)
        selectionPath.fill()
        selectionPath.stroke()
    }
    //绘制背景
    override func drawBackground(in dirtyRect: NSRect) {
        super.drawBackground(in: dirtyRect)
        NSColor.green.setFill()
        NSRectFill(dirtyRect)
    }
    
}

NSTableRowView相当于基于View-Base NSTableView的容器所在,它承载着所有的View。通过断点调试发现在每次初始化某个元素的具体视图之前都先调用初始化容器视图的方法,先把容器造好,再往里面加视图。例如上方代码:两列十行,每次先调用一次<code> rowViewForRow </code>方法把每行的容器造好然后再调用两次<code>viewFor tableColumn</code>方法来添加具体的视图。

六、关于NSTableRowView

NSTableRowView是基于View-Base的容器所在,在面介绍一些常用的属性及方法。

    //选中的高亮风格
    open var selectionHighlightStyle: NSTableViewSelectionHighlightStyle
    //是否强调
    open var isEmphasized: Bool
    //设置是否行组风格
    open var isGroupRowStyle: Bool
    //是否选中状态
    open var isSelected: Bool
    //其前一行的选中状态
    @available(OSX 10.10, *)
    open var isPreviousRowSelected: Bool
    //其后一行的选中状态
    open var isNextRowSelected: Bool
    //设置此行是否浮动
    open var isFloating: Bool
    //拖放拖动效果
    open var isTargetForDropOperation: Bool
    //拖放风格
    open var draggingDestinationFeedbackStyle: 
    //设置拖放目标的缩进量
    open var indentationForDropOperation: CGFloat
    //背景风格
    open var interiorBackgroundStyle: NSBackgroundStyle { get }
    //背景色
    @NSCopying open var backgroundColor: NSColor

    //子类重写下面方法来进行行容器视图的自定义
    //画背景色
    open func drawBackground(in dirtyRect: NSRect)
    //画选中背景
    open func drawSelection(in dirtyRect: NSRect)
    //画分割线
    open func drawSeparator(in dirtyRect: NSRect)
    //制拖放时的用户反馈IU
    open func drawDraggingDestinationFeedback(in dirtyRect: NSRect)
    //提供的访问特定视图的方法
    open func view(atColumn column: Int) -> Any?
    //列数
    open var numberOfColumns: Int { get }

七、总结NSTableViewDataSource协议

    //无论是基于Cell还是基于View这个是必须实现的方法,设置行数
    optional public func numberOfRows(in tableView: NSTableView) -> Int
    //如果使用cell-base的TableView视图,这个方法是必须实现的,其为要渲染的cell提供数据
    optional public func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
    //这个函数当用户编辑了cell中的内容时会被调用,一般需要在其中进行数据源的修改
    optional public func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int)
    //当用户修改了行排序规则时调用的回调
    optional public func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor])

    //面这些方法全部与列表的数据拖拽相关,具体可以参考Xcode文档
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting?
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forRowIndexes rowIndexes: IndexSet)
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation)
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, updateDraggingItemsForDrag draggingInfo: NSDraggingInfo)
    optional public func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool
    optional public func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableViewDropOperation) -> NSDragOperation
    optional public func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableViewDropOperation) -> Bool
    optional public func tableView(_ tableView: NSTableView, namesOfPromisedFilesDroppedAtDestination dropDestination: URL, forDraggedRowsWith indexSet: IndexSet) -> [String]

八、总结NSTableViewDelegate协议

    //基于View-Base的NSTableView相关Delegate方法
    //设置每个数据载体的View
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?
    //设置每行的容器视图
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView?
    //添加行的方法
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, didAdd rowView: NSTableRowView, forRow row: Int)
    //删除行的方法
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, didRemove rowView: NSTableRowView, forRow row: Int)

    --------------------------------------这难道是分割线? --------------------------------------

    //基于Cell-Base的NSTableView相关Delegate方法
    //ell将要渲染时调用的回调,可以在其中对cell进行定制
    optional public func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int)
    //设置某个cell是否可以编辑
    optional public func tableView(_ tableView: NSTableView, shouldEdit tableColumn: NSTableColumn?, row: Int) -> Bool
    //设置当鼠标悬停在cell上时 显示的提示文案
    optional public func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String
    //当cell的宽度不够显示完全cell的内容时,设置是否允许鼠标放置扩展cell
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, shouldShowCellExpansionFor tableColumn: NSTableColumn?, row: Int) -> Bool
    //设置是否加强cell的交互能力,这样一些按钮状态的修改也会触发cell编辑的状态
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, shouldTrackCell cell: NSCell, for tableColumn: NSTableColumn?, row: Int) -> Bool
    //设置自定义cell
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell?

    --------------------------------------这难道是分割线? --------------------------------------

    //通用的代理方法
    //设置是否允许修改选中
    optional public func selectionShouldChange(in tableView: NSTableView) -> Bool
    //设置某行是否可以选中
    optional public func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool
    //当用户通过键盘或鼠标将要选中某行时,返回设置要选中的行,如果实现了这个方法,上面一个方法将不会被调用
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet) -> IndexSet
    //设置某列是否可以被选中
    optional public func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool
    //用户点击列头时调用的方法
    optional public func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn)
    //用法同上
    optional public func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn)
    //对列进行拖拽改变顺序时调用的方法
    optional public func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn)
    //设置行高
    optional public func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat
    //下面这些方法与行检索有关
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, typeSelectStringFor tableColumn: NSTableColumn?, row: Int) -> String?
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, nextTypeSelectMatchFromRow startRow: Int, toRow endRow: Int, for searchString: String) -> Int
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, shouldTypeSelectFor event: NSEvent, withCurrentSearch searchString: String?) -> Bool
    //设置某行是否绘制成组样式
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool
    //调整列宽度(本人测试时这个方法怎么也不调用,望大神指点)
    @available(OSX 10.6, *)
    optional public func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat
    //设置是否支持列的移动排序
    @available(OSX 10.6, *)
    optional public func tableView(_ tableView: NSTableView, shouldReorderColumn columnIndex: Int, toColumn newColumnIndex: Int) -> Bool
    ////设置某行向左或向右滑动时要显示的功能按钮
    @available(OSX 10.11, *)
    optional public func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableRowActionEdge) -> [NSTableViewRowAction]
    //TableView选中修改时调用
    optional public func tableViewSelectionDidChange(_ notification: Notification)
    //TableView列移动完成时调用的函数
    optional public func tableViewColumnDidMove(_ notification: Notification)
    //TableView列宽度变化时调用的函数
    optional public func tableViewColumnDidResize(_ notification: Notification)
    //TableView选中正在修改时调用的函数
    optional public func tableViewSelectionIsChanging(_ notification: Notification)

九、NSTableView中常用的属性和方法

    //构造方法
    public init(frame frameRect: NSRect)
    public init?(coder: NSCoder)
    
    //数据源和代理
    weak open var dataSource: NSTableViewDataSource?
    weak open var delegate: NSTableViewDelegate?
    //设置头视图,会被列头图就行覆盖
    open var headerView: NSTableHeaderView?
    //设置头图右侧视图 可以自定义图标
    open var cornerView: NSView?
    //设置是否允许列拖拽排序
    open var allowsColumnReordering: Bool
    //设置是否允许调整列宽度
    open var allowsColumnResizing: Bool
    //调整列宽度的风格
    open var columnAutoresizingStyle: NSTableViewColumnAutoresizingStyle
    //设置分割线风格
    open var gridStyleMask: NSTableViewGridLineStyle
    //设置cell之间的间隔 需要设置为NSSize对象
    open var intercellSpacing: NSSize
    //是否开启斑马线
    open var usesAlternatingRowBackgroundColors: Bool
    //背景颜色
    @NSCopying open var backgroundColor: NSColor
    //设置分割线颜色
    @NSCopying open var gridColor: NSColor
    //设置尺寸风格
    @available(OSX 10.7, *)
    open var rowSizeStyle: NSTableViewRowSizeStyle
    //设置有效的行类型
    @available(OSX 10.7, *)
    open var effectiveRowSizeStyle: NSTableViewRowSizeStyle { get }
    //行高
    open var rowHeight: CGFloat
    //记录行高度的改变
    open func noteHeightOfRows(withIndexesChanged indexSet: IndexSet)
    //获取所有列
    open var tableColumns: [NSTableColumn] { get }
    //列的个数
    open var numberOfColumns: Int { get }
    //行的个数
    open var numberOfRows: Int { get }
    //添加列
    open func addTableColumn(_ tableColumn: NSTableColumn)
    //删除列
    open func removeTableColumn(_ tableColumn: NSTableColumn)
    //移动列
    open func moveColumn(_ oldIndex: Int, toColumn newIndex: Int)
    //根据identifier获取某个列对象的下表
    open func column(withIdentifier identifier: String) -> Int
    //根据identifier获取某个列对象
    open func tableColumn(withIdentifier identifier: String) -> NSTableColumn?
    //标题
    open func tile()
    //进行自动尺寸的调整
    open func sizeToFit()
    //进行最后一列尺寸的调整
    open func sizeLastColumnToFit()
    //滚动到指定行可见
    open func scrollRowToVisible(_ row: Int)
    //滚动到指定列可见
    open func scrollColumnToVisible(_ column: Int)
    //重新加载数据
    open func reloadData()
    //记录行数的改变
    open func noteNumberOfRowsChanged()
    //重新加载指定位置的数据
    @available(OSX 10.6, *)
    open func reloadData(forRowIndexes rowIndexes: IndexSet, columnIndexes: IndexSet)
    //获取编辑的列
    open var editedColumn: Int { get }
    //获取编辑的行
    open var editedRow: Int { get }
    //获取点击的列
    open var clickedColumn: Int { get }
    //获取点击的行
    open var clickedRow: Int { get }
    //设置双击方法
    open var doubleAction: Selector?
    //排序回调函数
    open var sortDescriptors: [NSSortDescriptor]
    //设置列头提示图片
    open func setIndicatorImage(_ image: NSImage?, in tableColumn: NSTableColumn)
    //获取列头提示图片
    open func indicatorImage(in tableColumn: NSTableColumn) -> NSImage?
    //获取高亮的列
    unowned(unsafe) open var highlightedTableColumn: NSTableColumn?
    
    //下面这些方法与列表拖拽有关
    open var verticalMotionCanBeginDrag: Bool
    open func canDragRows(with rowIndexes: IndexSet, at mouseDownPoint: NSPoint) -> Bool
    open func dragImageForRows(with dragRows: IndexSet, tableColumns: [NSTableColumn], event dragEvent: NSEvent, offset dragImageOffset: NSPointPointer) -> NSImage
    open func setDraggingSourceOperationMask(_ mask: NSDragOperation, forLocal isLocal: Bool)
    open func setDropRow(_ row: Int, dropOperation: NSTableViewDropOperation)
    
    //下面这些方法和列表选中有关
    //是否支持多选
    open var allowsMultipleSelection: Bool
    //是否允许都不选中
    open var allowsEmptySelection: Bool
    //是否支持选中列 如果设置为YES 点击列头会将整列选中
    open var allowsColumnSelection: Bool
    //全选 用于子类重写
    open func selectAll(_ sender: Any?)
    //全不选 用于子类重写
    open func deselectAll(_ sender: Any?)
    //选中列
    open func selectColumnIndexes(_ indexes: IndexSet, byExtendingSelection extend: Bool)
    //选中行
    open func selectRowIndexes(_ indexes: IndexSet, byExtendingSelection extend: Bool)
    //获取所有选中的index
    open var selectedColumnIndexes: IndexSet { get }
    //获取所有选中的行
    open var selectedRowIndexes: IndexSet { get }
    //取消某列的选中
    open func deselectColumn(_ column: Int)
    //取消某行的选中
    open func deselectRow(_ row: Int)
    //获取被选中的列
    open var selectedColumn: Int { get }
    //获取被选中的行
    open var selectedRow: Int { get }
    //判断某列是否被选中
    open func isColumnSelected(_ column: Int) -> Bool
    //判断某行是否被选中
    open func isRowSelected(_ row: Int) -> Bool
    //获取选中的列数
    open var numberOfSelectedColumns: Int { get }
    //获取选中的行数
    open var numberOfSelectedRows: Int { get }
    //允许被选中
    @available(OSX 10.5, *)
    open var allowsTypeSelect: Bool
    //设置选中的高亮状态
    @available(OSX 10.5, *)
    open var selectionHighlightStyle: NSTableViewSelectionHighlightStyle
    //设置拖拽风格
    @available(OSX 10.6, *)
    open var draggingDestinationFeedbackStyle: NSTableViewDraggingDestinationFeedbackStyle
    //获取某列的位置尺寸
    open func rect(ofColumn column: Int) -> NSRect
    //获取某行的位置尺寸
    open func rect(ofRow row: Int) -> NSRect
    //获取某个范围内的列
    @available(OSX 10.5, *)
    open func columnIndexes(in rect: NSRect) -> IndexSet
    //获取某个范围内的行
    open func rows(in rect: NSRect) -> NSRange
    //获取包含某个点的列
    open func column(at point: NSPoint) -> Int
    //获取包含某个点的行
    open func row(at point: NSPoint) -> Int
    //获取某个cell的位置尺寸
    open func frameOfCell(atColumn column: Int, row: Int) -> NSRect
    //自动保存名字
    open var autosaveName: String?
    //是否自动保存列
    open var autosaveTableColumns: Bool
    //更改列
    open func editColumn(_ column: Int, row: Int, with event: NSEvent?, select: Bool)
    //手动绘制某行
    open func drawRow(_ row: Int, clipRect: NSRect)
    //绘制高亮选中状态
    open func highlightSelection(inClipRect clipRect: NSRect)
    //手动绘制网格
    open func drawGrid(inClipRect clipRect: NSRect)
    //手动绘制背景色
    open func drawBackground(inClipRect clipRect: NSRect)
    //获取某个位置的View,用于view-base
    @available(OSX 10.7, *)
    open func view(atColumn column: Int, row: Int, makeIfNecessary: Bool) -> NSView?
    //获取某行的视图 用于view-base
    @available(OSX 10.7, *)
    open func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView?
    //获取某个View所在的行 用于view-base
    @available(OSX 10.7, *)
    open func row(for view: NSView) -> Int
    //获取某个View所在的列 用于view-base
    @available(OSX 10.7, *)
    open func column(for view: NSView) -> Int
    //创建一个用于渲染的View 用于view-base
    @available(OSX 10.7, *)
    open func make(withIdentifier identifier: String, owner: Any?) -> NSView?
    //列出可用的行视图
    @available(OSX 10.7, *)
    open func enumerateAvailableRowViews(_ handler: (NSTableRowView, Int) -> Swift.Void)
    //是否允许某行浮动
    @available(OSX 10.7, *)
    open var floatsGroupRows: Bool
    //是否隐藏左右滑动时的功能按钮
    @available(OSX 10.11, *)
    open var rowActionsVisible: Bool
    
    //下面这些方法用来根据列表数据
    //开始更新
    @available(OSX 10.7, *)
    open func beginUpdates()
    //结束更新
    @available(OSX 10.7, *)
    open func endUpdates()
    //插入行
    @available(OSX 10.7, *)
    open func insertRows(at indexes: IndexSet, withAnimation animationOptions: NSTableViewAnimationOptions = [])
    //删除行
    @available(OSX 10.7, *)
    open func removeRows(at indexes: IndexSet, withAnimation animationOptions: NSTableViewAnimationOptions = [])
    //移动行
    @available(OSX 10.7, *)
    open func moveRow(at oldIndex: Int, to newIndex: Int)
    //隐藏行
    @available(OSX 10.11, *)
    open func hideRows(at indexes: IndexSet, withAnimation rowAnimation: NSTableViewAnimationOptions = [])
    //取消隐藏行
    @available(OSX 10.11, *)
    open func unhideRows(at indexes: IndexSet, withAnimation rowAnimation: NSTableViewAnimationOptions = [])
    //所有隐藏状态的行
    @available(OSX 10.11, *)
    open var hiddenRowIndexes: IndexSet { get }
    //注册某个NSNib类进行复用
    @available(OSX 10.8, *)
    open func register(_ nib: NSNib?, forIdentifier identifier: String)
    //获取注册过的NSNib
    @available(OSX 10.8, *)
    open var registeredNibsByIdentifier: [String : NSNib]? { get }
    //有行被添加时调用
    @available(OSX 10.7, *)
    open func didAdd(_ rowView: NSTableRowView, forRow row: Int)
    //有行被移动时调用
    @available(OSX 10.7, *)
    open func didRemove(_ rowView: NSTableRowView, forRow row: Int)
    //是否将tableView设置成静态
    @available(OSX 10.10, *)
    open var usesStaticContents: Bool
    //用户界面布局方向:枚举类型
    open var userInterfaceLayoutDirection: NSUserInterfaceLayoutDirection

总结

作者最近在学习macOS开发,发现NSTableView是macOS开发中很重要的控件,它不仅功能强大而且官方为我们提供的接口更加更富,这让我们学习起来容易入手,以上全是个人最近学习的总结,如有不妥之处请指教,谢谢。

作者:Olivia_Zqy

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容