Mac開發(fā) NSTableView(代碼詳解)

轉(zhuǎn)載請(qǐng)聯(lián)系作者獲取授權(quán),并標(biāo)明文章作者,謝謝!

一、前言

本文所有代碼基于Xcode8.3.3,Swift3.0開發(fā)。
NSTableView是macOS開發(fā)中很重要的控件,用于滾動(dòng)數(shù)據(jù),表格數(shù)據(jù)等復(fù)雜視圖的實(shí)現(xiàn)。首先如果想要實(shí)現(xiàn)NSTableView的滾動(dòng)效果需要將它承載在一個(gè)NSScrollView里。和iOS中的UITableView類似數(shù)據(jù)源也是DataSource,視圖屬性也是由Delegate控制。

在OS X v10.6版本之前,NSTableView中行數(shù)據(jù)載體視圖必須是NSCell的子類,之后版本的OS X支持開發(fā)者創(chuàng)建基于View的TableView視圖,同樣也支持基于Cell的TabelView視圖,在開發(fā)者,我們可以根據(jù)實(shí)際需求選擇。

二、構(gòu)建一個(gè)簡(jiǎn)單的NSTableView視圖

創(chuàng)建一個(gè)WindowVC在里面構(gòu)建NSTableView。
關(guān)于NSWindowController的簡(jiǎn)述和創(chuàng)建請(qǐng)看這篇文章: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.
        //初始化數(shù)據(jù)源
        for i in 0..<10{
            let dataStr = "第\(i+1)條數(shù)據(jù)"
            dataSource.append(dataStr)
        }
        //初始化ScrollView用于承載tableView附有滾動(dòng)效果
        let scrollView = NSScrollView()
        scrollView.hasVerticalScroller = true
        scrollView.frame = CGRect.zero
        self.window?.contentView?.addSubview(scrollView)
        scrollView.snp.makeConstraints { (make) in
            make.edges.equalTo(0)
        }
        //初始化兩個(gè)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)
        //允許自動(dòng)調(diào)整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)
        }
        
    }

下面是代理方法的實(shí)現(xiàn):

    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:)")
    }

工程運(yùn)行效果如下圖:

Cell-Base工程運(yùn)行效果

我們來(lái)分析一下這個(gè)tableView的實(shí)現(xiàn):這是一個(gè)典型的基于Cell-Base的NSTableView,數(shù)據(jù)核心代碼是<code>objectValueFor tableColumn:</code>方法,和UITableView一樣需要實(shí)現(xiàn)<code>numberOfRows,heightOfRow</code>方法,在<code>objectValueFor tableColumn:</code>方法中我們可以通過(guò)<code>tableColumn?.identifier</code>來(lái)指定我們之前添加的NSColumn從而可以確定每一列的每一行數(shù)據(jù)。

三、關(guān)于NSColumn

NSColumn可以理解為NSTableView的一列,我們可以給某一列設(shè)置一些屬性(寬度,標(biāo)題,編輯狀態(tài)...等)。下面列舉NSColumn的常用屬性。

//初始化方法,指定一個(gè)列ID
public init(identifier: String)
//與此列關(guān)聯(lián)的ID
open var identifier: String
//關(guān)聯(lián)的TableView
unowned(unsafe) open var tableView: NSTableView?
//設(shè)置列寬度
open var width: CGFloat
//設(shè)置最小列寬度
open var minWidth: CGFloat
//設(shè)置最大列寬度
open var maxWidth: CGFloat
//設(shè)置類標(biāo)題
open var title: String
/*
列標(biāo)題視圖 開發(fā)者可以對(duì)其進(jìn)行修改
需要注意,NSTableHeaderCell是繼承自NSTextFieldCell
*/
open var headerCell: NSTableHeaderCell
//設(shè)置此列是否可以進(jìn)行編輯
open var isEditable: Bool
//進(jìn)行列尺寸的調(diào)整 以列標(biāo)題視圖的寬度為標(biāo)準(zhǔn) 
open func sizeToFit()
//提供了這個(gè)屬性,會(huì)在列標(biāo)題那里顯示一個(gè)排序按鈕 點(diǎn)擊列標(biāo)題后可以進(jìn)行排序操作(會(huì)回調(diào)相關(guān)協(xié)議方法)
@NSCopying open var sortDescriptorPrototype: NSSortDescriptor?
//設(shè)置列尺寸的調(diào)整模式 枚舉如下
/*
public struct NSTableColumnResizingOptions : OptionSet {
    public init(rawValue: UInt)
    public static var autoresizingMask: NSTableColumnResizingOptions { get } //使用tableView的column調(diào)整策略
    public static var userResizingMask: NSTableColumnResizingOptions { get }//允許用戶進(jìn)行尺寸調(diào)整
}
*/
open var resizingMask: NSTableColumnResizingOptions
//設(shè)置列頭的提示標(biāo)題 當(dāng)鼠標(biāo)懸停在類標(biāo)題上時(shí)  會(huì)顯示此提示
open var headerToolTip: String?;
//設(shè)置此列是否隱藏
open var isHidden: Bool
//設(shè)置此列所有行的數(shù)據(jù)載體視圖 如果不設(shè)置 默認(rèn)為NSTextFieldCell
open var dataCell: Any
//為TableView列表提供數(shù)據(jù)載體視圖
open func dataCell(forRow row: Int) -> Any

四、Cell-Base:基于Cell的NSTableView

Cell-Base的NSTableView是macOS早起開發(fā)的主要結(jié)構(gòu),其每一個(gè)載體都必須是基于NSCell或者其子類,必須實(shí)現(xiàn)<code> numberOfRows </code>和<code>objectValueFor tableColumn</code>兩個(gè)方法。第一個(gè)方法設(shè)置行數(shù),第二個(gè)給每個(gè)Cell載體賦予數(shù)據(jù)。需要注意,如果只實(shí)現(xiàn)這兩個(gè)方法,則NSTableView會(huì)自動(dòng)從列對(duì)象NSTableColume中取具體的行視圖,通過(guò)dataCellForRow方法。

當(dāng)<code>objectValueForTableColum </code>方法將每個(gè)行具體的數(shù)據(jù)返回后,編輯時(shí)會(huì)調(diào)用cell的<code>setObjectValue</code>方法(因此如果要自定義cell,必須實(shí)現(xiàn)這個(gè)方法)。如果我們要對(duì)Cell的渲染進(jìn)行一些定制,可以在如下方法中實(shí)現(xiàn):

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

實(shí)現(xiàn)下面的方法可以返回一個(gè)自定義的Cell,如果實(shí)現(xiàn)了這個(gè)方法,則TableView不會(huì)再?gòu)腘STableColumn對(duì)象中拿Cell實(shí)例。

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

全部代碼如下:(NSTalbeView和NSScrollView的創(chuàng)建以及屬性和上方示例1代碼一樣,故下方只列舉代理方法)

    //設(shè)置行數(shù) 通用
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 10
    }
    //設(shè)置行高度 通用
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        return 40
    }
    //綁定數(shù)據(jù)源
    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
    }
    //排序回調(diào)函數(shù)
    func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
        print("oldDescriptors[0] -> (sortDescriptorPrototyp, descending, compare:)")
    }
    //cell-base的cell展示前調(diào)用 可以進(jìn)行自定制
    func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int) {
        let tmpCell = cell as! NSTextFieldCell
        tmpCell.textColor = NSColor.red
    }
    //設(shè)置是否可以進(jìn)行編輯
    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
    }
    //設(shè)置鼠標(biāo)懸停在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 ""
    }
    //當(dāng)列表長(zhǎng)度無(wú)法展示完整某行數(shù)據(jù)時(shí) 當(dāng)鼠標(biāo)懸停在此行上 是否擴(kuò)展顯示
    func tableView(_ tableView: NSTableView, shouldShowCellExpansionFor tableColumn: NSTableColumn?, row: Int) -> Bool {
        return true
    }
    //設(shè)置cell的交互能力
    /*
     如果返回YES,則Cell的交互能力會(huì)變強(qiáng),例如NSButtonCell的點(diǎn)擊將會(huì)調(diào)用- (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的子類來(lái)作為NSTableView的載體,書寫方式,自定義方式等更加簡(jiǎn)單易用,示例代碼:

   //設(shè)置行數(shù) 通用
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 10
    }
    //設(shè)置行高度 通用
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        return 40
    }
    //View-base
    //設(shè)置某個(gè)元素的具體視圖
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        
        let key = tableColumn?.identifier
        //根據(jù)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!)列的數(shù)據(jù),\(dataSource[row])"
        return view;
    }
    //設(shè)置每行容器視圖
    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
    }
    //當(dāng)添加行時(shí)調(diào)用的回調(diào)
    func tableView(_ tableView: NSTableView, didAdd rowView: NSTableRowView, forRow row: Int) {
        print("addRow")
    }
    //當(dāng)移除行時(shí)調(diào)用的回調(diào)
    func tableView(_ tableView: NSTableView, didRemove rowView: NSTableRowView, forRow row: Int) {
        print("removeRow")
    }

下面是運(yùn)行效果:

View-Base工程運(yùn)行效果

上面代碼中用到了TableRow類,其實(shí)它是一個(gè)自定義的繼承自NSTableRowView的類,實(shí)現(xiàn)如下:

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")
    }
    //繪制選中狀態(tài)的背景
    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相當(dāng)于基于View-Base NSTableView的容器所在,它承載著所有的View。通過(guò)斷點(diǎn)調(diào)試發(fā)現(xiàn)在每次初始化某個(gè)元素的具體視圖之前都先調(diào)用初始化容器視圖的方法,先把容器造好,再往里面加視圖。例如上方代碼:兩列十行,每次先調(diào)用一次<code> rowViewForRow </code>方法把每行的容器造好然后再調(diào)用兩次<code>viewFor tableColumn</code>方法來(lái)添加具體的視圖。

六、關(guān)于NSTableRowView

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

    //選中的高亮風(fēng)格
    open var selectionHighlightStyle: NSTableViewSelectionHighlightStyle
    //是否強(qiáng)調(diào)
    open var isEmphasized: Bool
    //設(shè)置是否行組風(fēng)格
    open var isGroupRowStyle: Bool
    //是否選中狀態(tài)
    open var isSelected: Bool
    //其前一行的選中狀態(tài)
    @available(OSX 10.10, *)
    open var isPreviousRowSelected: Bool
    //其后一行的選中狀態(tài)
    open var isNextRowSelected: Bool
    //設(shè)置此行是否浮動(dòng)
    open var isFloating: Bool
    //拖放拖動(dòng)效果
    open var isTargetForDropOperation: Bool
    //拖放風(fēng)格
    open var draggingDestinationFeedbackStyle: 
    //設(shè)置拖放目標(biāo)的縮進(jìn)量
    open var indentationForDropOperation: CGFloat
    //背景風(fēng)格
    open var interiorBackgroundStyle: NSBackgroundStyle { get }
    //背景色
    @NSCopying open var backgroundColor: NSColor

    //子類重寫下面方法來(lái)進(jìn)行行容器視圖的自定義
    //畫背景色
    open func drawBackground(in dirtyRect: NSRect)
    //畫選中背景
    open func drawSelection(in dirtyRect: NSRect)
    //畫分割線
    open func drawSeparator(in dirtyRect: NSRect)
    //制拖放時(shí)的用戶反饋IU
    open func drawDraggingDestinationFeedback(in dirtyRect: NSRect)
    //提供的訪問特定視圖的方法
    open func view(atColumn column: Int) -> Any?
    //列數(shù)
    open var numberOfColumns: Int { get }

七、總結(jié)NSTableViewDataSource協(xié)議

    //無(wú)論是基于Cell還是基于View這個(gè)是必須實(shí)現(xiàn)的方法,設(shè)置行數(shù)
    optional public func numberOfRows(in tableView: NSTableView) -> Int
    //如果使用cell-base的TableView視圖,這個(gè)方法是必須實(shí)現(xiàn)的,其為要渲染的cell提供數(shù)據(jù)
    optional public func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
    //這個(gè)函數(shù)當(dāng)用戶編輯了cell中的內(nèi)容時(shí)會(huì)被調(diào)用,一般需要在其中進(jìn)行數(shù)據(jù)源的修改
    optional public func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int)
    //當(dāng)用戶修改了行排序規(guī)則時(shí)調(diào)用的回調(diào)
    optional public func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor])

    //面這些方法全部與列表的數(shù)據(jù)拖拽相關(guān),具體可以參考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]

八、總結(jié)NSTableViewDelegate協(xié)議

    //基于View-Base的NSTableView相關(guān)Delegate方法
    //設(shè)置每個(gè)數(shù)據(jù)載體的View
    @available(OSX 10.7, *)
    optional public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?
    //設(shè)置每行的容器視圖
    @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相關(guān)Delegate方法
    //ell將要渲染時(shí)調(diào)用的回調(diào),可以在其中對(duì)cell進(jìn)行定制
    optional public func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int)
    //設(shè)置某個(gè)cell是否可以編輯
    optional public func tableView(_ tableView: NSTableView, shouldEdit tableColumn: NSTableColumn?, row: Int) -> Bool
    //設(shè)置當(dāng)鼠標(biāo)懸停在cell上時(shí) 顯示的提示文案
    optional public func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String
    //當(dāng)cell的寬度不夠顯示完全cell的內(nèi)容時(shí),設(shè)置是否允許鼠標(biāo)放置擴(kuò)展cell
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, shouldShowCellExpansionFor tableColumn: NSTableColumn?, row: Int) -> Bool
    //設(shè)置是否加強(qiáng)cell的交互能力,這樣一些按鈕狀態(tài)的修改也會(huì)觸發(fā)cell編輯的狀態(tài)
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, shouldTrackCell cell: NSCell, for tableColumn: NSTableColumn?, row: Int) -> Bool
    //設(shè)置自定義cell
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell?

    --------------------------------------這難道是分割線? --------------------------------------

    //通用的代理方法
    //設(shè)置是否允許修改選中
    optional public func selectionShouldChange(in tableView: NSTableView) -> Bool
    //設(shè)置某行是否可以選中
    optional public func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool
    //當(dāng)用戶通過(guò)鍵盤或鼠標(biāo)將要選中某行時(shí),返回設(shè)置要選中的行,如果實(shí)現(xiàn)了這個(gè)方法,上面一個(gè)方法將不會(huì)被調(diào)用
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet) -> IndexSet
    //設(shè)置某列是否可以被選中
    optional public func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool
    //用戶點(diǎn)擊列頭時(shí)調(diào)用的方法
    optional public func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn)
    //用法同上
    optional public func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn)
    //對(duì)列進(jìn)行拖拽改變順序時(shí)調(diào)用的方法
    optional public func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn)
    //設(shè)置行高
    optional public func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat
    //下面這些方法與行檢索有關(guān)
    @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
    //設(shè)置某行是否繪制成組樣式
    @available(OSX 10.5, *)
    optional public func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool
    //調(diào)整列寬度(本人測(cè)試時(shí)這個(gè)方法怎么也不調(diào)用,望大神指點(diǎn))
    @available(OSX 10.6, *)
    optional public func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat
    //設(shè)置是否支持列的移動(dòng)排序
    @available(OSX 10.6, *)
    optional public func tableView(_ tableView: NSTableView, shouldReorderColumn columnIndex: Int, toColumn newColumnIndex: Int) -> Bool
    ////設(shè)置某行向左或向右滑動(dòng)時(shí)要顯示的功能按鈕
    @available(OSX 10.11, *)
    optional public func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableRowActionEdge) -> [NSTableViewRowAction]
    //TableView選中修改時(shí)調(diào)用
    optional public func tableViewSelectionDidChange(_ notification: Notification)
    //TableView列移動(dòng)完成時(shí)調(diào)用的函數(shù)
    optional public func tableViewColumnDidMove(_ notification: Notification)
    //TableView列寬度變化時(shí)調(diào)用的函數(shù)
    optional public func tableViewColumnDidResize(_ notification: Notification)
    //TableView選中正在修改時(shí)調(diào)用的函數(shù)
    optional public func tableViewSelectionIsChanging(_ notification: Notification)

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

    //構(gòu)造方法
    public init(frame frameRect: NSRect)
    public init?(coder: NSCoder)
    
    //數(shù)據(jù)源和代理
    weak open var dataSource: NSTableViewDataSource?
    weak open var delegate: NSTableViewDelegate?
    //設(shè)置頭視圖,會(huì)被列頭圖就行覆蓋
    open var headerView: NSTableHeaderView?
    //設(shè)置頭圖右側(cè)視圖 可以自定義圖標(biāo)
    open var cornerView: NSView?
    //設(shè)置是否允許列拖拽排序
    open var allowsColumnReordering: Bool
    //設(shè)置是否允許調(diào)整列寬度
    open var allowsColumnResizing: Bool
    //調(diào)整列寬度的風(fēng)格
    open var columnAutoresizingStyle: NSTableViewColumnAutoresizingStyle
    //設(shè)置分割線風(fēng)格
    open var gridStyleMask: NSTableViewGridLineStyle
    //設(shè)置cell之間的間隔 需要設(shè)置為NSSize對(duì)象
    open var intercellSpacing: NSSize
    //是否開啟斑馬線
    open var usesAlternatingRowBackgroundColors: Bool
    //背景顏色
    @NSCopying open var backgroundColor: NSColor
    //設(shè)置分割線顏色
    @NSCopying open var gridColor: NSColor
    //設(shè)置尺寸風(fēng)格
    @available(OSX 10.7, *)
    open var rowSizeStyle: NSTableViewRowSizeStyle
    //設(shè)置有效的行類型
    @available(OSX 10.7, *)
    open var effectiveRowSizeStyle: NSTableViewRowSizeStyle { get }
    //行高
    open var rowHeight: CGFloat
    //記錄行高度的改變
    open func noteHeightOfRows(withIndexesChanged indexSet: IndexSet)
    //獲取所有列
    open var tableColumns: [NSTableColumn] { get }
    //列的個(gè)數(shù)
    open var numberOfColumns: Int { get }
    //行的個(gè)數(shù)
    open var numberOfRows: Int { get }
    //添加列
    open func addTableColumn(_ tableColumn: NSTableColumn)
    //刪除列
    open func removeTableColumn(_ tableColumn: NSTableColumn)
    //移動(dòng)列
    open func moveColumn(_ oldIndex: Int, toColumn newIndex: Int)
    //根據(jù)identifier獲取某個(gè)列對(duì)象的下表
    open func column(withIdentifier identifier: String) -> Int
    //根據(jù)identifier獲取某個(gè)列對(duì)象
    open func tableColumn(withIdentifier identifier: String) -> NSTableColumn?
    //標(biāo)題
    open func tile()
    //進(jìn)行自動(dòng)尺寸的調(diào)整
    open func sizeToFit()
    //進(jìn)行最后一列尺寸的調(diào)整
    open func sizeLastColumnToFit()
    //滾動(dòng)到指定行可見
    open func scrollRowToVisible(_ row: Int)
    //滾動(dòng)到指定列可見
    open func scrollColumnToVisible(_ column: Int)
    //重新加載數(shù)據(jù)
    open func reloadData()
    //記錄行數(shù)的改變
    open func noteNumberOfRowsChanged()
    //重新加載指定位置的數(shù)據(jù)
    @available(OSX 10.6, *)
    open func reloadData(forRowIndexes rowIndexes: IndexSet, columnIndexes: IndexSet)
    //獲取編輯的列
    open var editedColumn: Int { get }
    //獲取編輯的行
    open var editedRow: Int { get }
    //獲取點(diǎn)擊的列
    open var clickedColumn: Int { get }
    //獲取點(diǎn)擊的行
    open var clickedRow: Int { get }
    //設(shè)置雙擊方法
    open var doubleAction: Selector?
    //排序回調(diào)函數(shù)
    open var sortDescriptors: [NSSortDescriptor]
    //設(shè)置列頭提示圖片
    open func setIndicatorImage(_ image: NSImage?, in tableColumn: NSTableColumn)
    //獲取列頭提示圖片
    open func indicatorImage(in tableColumn: NSTableColumn) -> NSImage?
    //獲取高亮的列
    unowned(unsafe) open var highlightedTableColumn: NSTableColumn?
    
    //下面這些方法與列表拖拽有關(guān)
    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)
    
    //下面這些方法和列表選中有關(guān)
    //是否支持多選
    open var allowsMultipleSelection: Bool
    //是否允許都不選中
    open var allowsEmptySelection: Bool
    //是否支持選中列 如果設(shè)置為YES 點(diǎn)擊列頭會(huì)將整列選中
    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
    //獲取選中的列數(shù)
    open var numberOfSelectedColumns: Int { get }
    //獲取選中的行數(shù)
    open var numberOfSelectedRows: Int { get }
    //允許被選中
    @available(OSX 10.5, *)
    open var allowsTypeSelect: Bool
    //設(shè)置選中的高亮狀態(tài)
    @available(OSX 10.5, *)
    open var selectionHighlightStyle: NSTableViewSelectionHighlightStyle
    //設(shè)置拖拽風(fēng)格
    @available(OSX 10.6, *)
    open var draggingDestinationFeedbackStyle: NSTableViewDraggingDestinationFeedbackStyle
    //獲取某列的位置尺寸
    open func rect(ofColumn column: Int) -> NSRect
    //獲取某行的位置尺寸
    open func rect(ofRow row: Int) -> NSRect
    //獲取某個(gè)范圍內(nèi)的列
    @available(OSX 10.5, *)
    open func columnIndexes(in rect: NSRect) -> IndexSet
    //獲取某個(gè)范圍內(nèi)的行
    open func rows(in rect: NSRect) -> NSRange
    //獲取包含某個(gè)點(diǎn)的列
    open func column(at point: NSPoint) -> Int
    //獲取包含某個(gè)點(diǎn)的行
    open func row(at point: NSPoint) -> Int
    //獲取某個(gè)cell的位置尺寸
    open func frameOfCell(atColumn column: Int, row: Int) -> NSRect
    //自動(dòng)保存名字
    open var autosaveName: String?
    //是否自動(dòng)保存列
    open var autosaveTableColumns: Bool
    //更改列
    open func editColumn(_ column: Int, row: Int, with event: NSEvent?, select: Bool)
    //手動(dòng)繪制某行
    open func drawRow(_ row: Int, clipRect: NSRect)
    //繪制高亮選中狀態(tài)
    open func highlightSelection(inClipRect clipRect: NSRect)
    //手動(dòng)繪制網(wǎng)格
    open func drawGrid(inClipRect clipRect: NSRect)
    //手動(dòng)繪制背景色
    open func drawBackground(inClipRect clipRect: NSRect)
    //獲取某個(gè)位置的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?
    //獲取某個(gè)View所在的行 用于view-base
    @available(OSX 10.7, *)
    open func row(for view: NSView) -> Int
    //獲取某個(gè)View所在的列 用于view-base
    @available(OSX 10.7, *)
    open func column(for view: NSView) -> Int
    //創(chuàng)建一個(gè)用于渲染的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)
    //是否允許某行浮動(dòng)
    @available(OSX 10.7, *)
    open var floatsGroupRows: Bool
    //是否隱藏左右滑動(dòng)時(shí)的功能按鈕
    @available(OSX 10.11, *)
    open var rowActionsVisible: Bool
    
    //下面這些方法用來(lái)根據(jù)列表數(shù)據(jù)
    //開始更新
    @available(OSX 10.7, *)
    open func beginUpdates()
    //結(jié)束更新
    @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 = [])
    //移動(dòng)行
    @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 = [])
    //所有隱藏狀態(tài)的行
    @available(OSX 10.11, *)
    open var hiddenRowIndexes: IndexSet { get }
    //注冊(cè)某個(gè)NSNib類進(jìn)行復(fù)用
    @available(OSX 10.8, *)
    open func register(_ nib: NSNib?, forIdentifier identifier: String)
    //獲取注冊(cè)過(guò)的NSNib
    @available(OSX 10.8, *)
    open var registeredNibsByIdentifier: [String : NSNib]? { get }
    //有行被添加時(shí)調(diào)用
    @available(OSX 10.7, *)
    open func didAdd(_ rowView: NSTableRowView, forRow row: Int)
    //有行被移動(dòng)時(shí)調(diào)用
    @available(OSX 10.7, *)
    open func didRemove(_ rowView: NSTableRowView, forRow row: Int)
    //是否將tableView設(shè)置成靜態(tài)
    @available(OSX 10.10, *)
    open var usesStaticContents: Bool
    //用戶界面布局方向:枚舉類型
    open var userInterfaceLayoutDirection: NSUserInterfaceLayoutDirection

總結(jié)

作者最近在學(xué)習(xí)macOS開發(fā),發(fā)現(xiàn)NSTableView是macOS開發(fā)中很重要的控件,它不僅功能強(qiáng)大而且官方為我們提供的接口更加更富,這讓我們學(xué)習(xí)起來(lái)容易入手,以上全是個(gè)人最近學(xué)習(xí)的總結(jié),如有不妥之處請(qǐng)指教,謝謝。

作者:Olivia_Zqy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容