五、View-Base:基于View的TableView視圖
基于View-Base的TableView要比基于Cell的TableView更加靈活,其中每行資料載體可以是任意NSView的子類。代碼示例如下:
//
// ViewController.m
// TableView
// Created by jaki on 17/4/14.
// Copyright © 2017年 jaki. All rights reserved.
#import "ViewController.h"
#import "MyCell.h"
#import "TableRow.h"
@interface ViewController()<NSTableViewDelegate,NSTableViewDataSource>
@end
@implementation ViewController
{
NSTableView * _tableView;
NSMutableArray * _dataArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
_dataArray = [NSMutableArray array];
for (int i=0; i<20; i++) {
[_dataArray addObject:[NSString stringWithFormat:@"%d行資料",i]];
}
NSScrollView * scrollView = [[NSScrollView alloc] init];
scrollView.hasVerticalScroller = YES;
scrollView.frame = self.view.bounds;
[self.view addSubview:scrollView];
_tableView = [[NSTableView alloc]initWithFrame:self.view.bounds];
NSTableColumn * column = [[NSTableColumn alloc]initWithIdentifier:@"test"];
NSTableColumn * column2 = [[NSTableColumn alloc]initWithIdentifier:@"test2"];
column2.width = 100;
column2.minWidth = 100;
column2.maxWidth = 100;
column2.title = @"資料";
column2.editable = YES ;
column2.headerToolTip = @"提示";
column2.hidden=NO;
column2.sortDescriptorPrototype = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:NO];
column.resizingMask =NSTableColumnUserResizingMask;
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView addTableColumn:column];
[_tableView addTableColumn:column2];
scrollView.contentView.documentView = _tableView;
//設定行數 通用
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
return _dataArray.count;
//View-base
//設定某個元素的具體視圖
- (nullable NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{
//根據ID取視圖
NSTextField * view = [tableView makeViewWithIdentifier:@"cellId" owner:self];
if (view==nil) {
view = [[NSTextField alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
view.backgroundColor = [NSColor clearColor];
view.identifier = @"cellId";
return view;
//設定每行容器視圖
- (nullable NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row{
TableRow * rowView = [[TableRow alloc]init];
return rowView;
//當添加行時調用的回調
- (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row{
NSLog(@"add");
//當移除行時調用的回調
- (void)tableView:(NSTableView *)tableView didRemoveRowView:(NSTableRowView *)rowView forRow:(NSInteger)row{
NSLog(@"remove");
上面代碼中用到了TableRow類,其實它是一個自定義的繼承自NSTableRowView的類,實作如下:
#import "TablerRow.h"
@implementation TablerRow
//繪制選中狀态的背景
-(void)drawSelectionInRect:(NSRect)dirtyRect{
NSRect selectionRect = NSInsetRect(self.bounds, 5.5, 5.5);
[[NSColor colorWithCalibratedWhite:.72 alpha:1.0] setStroke];
[[NSColor colorWithCalibratedWhite:.82 alpha:1.0] setFill];
NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:10 yRadius:10];
[selectionPath fill];
[selectionPath stroke];
//繪制背景
-(void)drawBackgroundInRect:(NSRect)dirtyRect{
[super drawBackgroundInRect:dirtyRect];
[[NSColor greenColor]setFill];
NSRectFill(dirtyRect);
關于NSTableRowView類我們下面來做具體介紹。
六、NSTableRowView解析
NSTableRowView用在View-Base的TableView中,其作為行容器存在。
//選中的高亮風格
/*
typedef NS_ENUM(NSInteger, NSTableViewSelectionHighlightStyle) {
//無高亮風格
NSTableViewSelectionHighlightStyleNone,
//規則的高亮風格
NSTableViewSelectionHighlightStyleRegular = 0,
//源清單風格
NSTableViewSelectionHighlightStyleSourceList = 1,
};
*/
@property NSTableViewSelectionHighlightStyle selectionHighlightStyle;
//是否強調
@property(getter=isEmphasized) BOOL emphasized;
//設定是否行組風格
@property(getter=isGroupRowStyle) BOOL groupRowStyle;
//是否選中狀态
@property(getter=isSelected) BOOL selected;
//其前一行的選中狀态
@property(getter=isPreviousRowSelected) BOOL previousRowSelected;
//其後一行的選中狀态
@property(getter=isNextRowSelected) BOOL nextRowSelected;
//設定此行是否浮動
@property(getter=isFloating) BOOL floating;
//拖放拖動效果
@property(getter=isTargetForDropOperation) BOOL targetForDropOperation;
//拖放風格
@property NSTableViewDraggingDestinationFeedbackStyle draggingDestinationFeedbackStyle;
//設定拖放目标的縮進量
@property CGFloat indentationForDropOperation;
//背景色
@property(copy) NSColor *backgroundColor;
//子類重寫下面方法來進行行容器視圖的自定義
//畫背景色
- (void)drawBackgroundInRect:(NSRect)dirtyRect;
//畫選中背景
- (void)drawSelectionInRect:(NSRect)dirtyRect;
//畫分割線
- (void)drawSeparatorInRect:(NSRect)dirtyRect;
//繪制拖放時的使用者回報IU
- (void)drawDraggingDestinationFeedbackInRect:(NSRect)dirtyRect;
//列數
@property(readonly) NSInteger numberOfColumns;
//提供的通路特定視圖的方法
- (nullable id)viewAtColumn:(NSInteger)column;
七、來總結下NSTableViewDataSource協定
無論基于Cell還是基于View,這個方法都需要實作,用來設定清單的行數
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView;
如果使用cell-base的TableView視圖,這個方法是必須實作的,其為要渲染的cell提供資料
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
這個函數當使用者編輯了cell中的内容時會被調用,一般需要在其中進行資料源的修改
- (void)tableView:(NSTableView *)tableView setObjectValue:(nullable id)object forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
當使用者修改了行排序規則時調用的回調
- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors;
//下面這些方法全部與清單的資料拖拽相關
- (nullable id <NSPasteboardWriting>)tableView:(NSTableView *)tableView pasteboardWriterForRow:(NSInteger)row;
- (void)tableView:(NSTableView *)tableView draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forRowIndexes:(NSIndexSet *)rowIndexes NS_AVAILABLE_MAC(10_7);
- (void)tableView:(NSTableView *)tableView draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation NS_AVAILABLE_MAC(10_7);
- (void)tableView:(NSTableView *)tableView updateDraggingItemsForDrag:(id <NSDraggingInfo>)draggingInfo NS_AVAILABLE_MAC(10_7);
- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard;
- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation;
- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation;
- (NSArray<NSString *> *)tableView:(NSTableView *)tableView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedRowsWithIndexes:(NSIndexSet *)indexSet;
八、來總結下NSTableViewDelegate協定
//view-base的TableView相關delegate方法
設定每個資料載體的View
- (nullable NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
自定義行視圖
- (nullable NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row NS_AVAILABLE_MAC(10_7);
添加一行時會調用的回調
- (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row;
移除一行時會調用的回調
- (void)tableView:(NSTableView *)tableView didRemoveRowView:(NSTableRowView *)rowView forRow:(NSInteger)row;
//cell-base的TableView相關delegate方法
cell将要渲染時調用的回調,可以在其中對cell進行定制
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
設定某個cell是否可以編輯
- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
設定當滑鼠懸停在cell上時 顯示的提示文案
- (NSString *)tableView:(NSTableView *)tableView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation;
當cell的寬度不夠顯示完全cell的内容時,設定是否允許滑鼠放置擴充cell
- (BOOL)tableView:(NSTableView *)tableView shouldShowCellExpansionForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
設定是否加強cell的互動能力,這樣一些按鈕狀态的修改也會觸發cell編輯的狀态
- (BOOL)tableView:(NSTableView *)tableView shouldTrackCell:(NSCell *)cell forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
設定自定義cell
- (nullable NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;
//通用的TableView代理方法
設定是否允許修改選中
- (BOOL)selectionShouldChangeInTableView:(NSTableView *)tableView;
設定某行是否可以選中
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
當使用者通過鍵盤或滑鼠将要選中某行時,傳回設定要選中的行
如果實作了這個方法,上面一個方法将不會被調用
- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes;
設定某列是否可以被選中
- (BOOL)tableView:(NSTableView *)tableView shouldSelectTableColumn:(nullable NSTableColumn *)tableColumn;
使用者點選列頭時調用的方法
- (void)tableView:(NSTableView *)tableView mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn;
用法同上
- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn;
對列進行拖拽改變順序時調用的方法
- (void)tableView:(NSTableView *)tableView didDragTableColumn:(NSTableColumn *)tableColumn;
設定行高
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row;
下面這些方法與行檢索有關
- (nullable NSString *)tableView:(NSTableView *)tableView typeSelectStringForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row NS_AVAILABLE_MAC(10_5);
- (NSInteger)tableView:(NSTableView *)tableView nextTypeSelectMatchFromRow:(NSInteger)startRow toRow:(NSInteger)endRow forString:(NSString *)searchString NS_AVAILABLE_MAC(10_5);
- (BOOL)tableView:(NSTableView *)tableView shouldTypeSelectForEvent:(NSEvent *)event withCurrentSearchString:(nullable NSString *)searchString NS_AVAILABLE_MAC(10_5);
設定某行是否繪制成組樣式
- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row;
調整列寬度
- (CGFloat)tableView:(NSTableView *)tableView sizeToFitWidthOfColumn:(NSInteger)column;
設定是否支援列的移動排序
- (BOOL)tableView:(NSTableView *)tableView shouldReorderColumn:(NSInteger)columnIndex toColumn:(NSInteger)newColumnIndex;
//設定某行向左或向右滑動時要顯示的功能按鈕
typedef NS_ENUM(NSInteger, NSTableRowActionEdge) {
NSTableRowActionEdgeLeading, // 左劃
NSTableRowActionEdgeTrailing, // 右劃
} NS_ENUM_AVAILABLE_MAC(10_11);
- (NSArray<NSTableViewRowAction *> *)tableView:(NSTableView *)tableView rowActionsForRow:(NSInteger)row edge:(NSTableRowActionEdge)edge NS_AVAILABLE_MAC(10_11);
TableView選中修改時調用
- (void)tableViewSelectionDidChange:(NSNotification *)notification;
TableView列移動完成時調用的函數
- (void)tableViewColumnDidMove:(NSNotification *)notification;
TableView列寬度變化時調用的函數
- (void)tableViewColumnDidResize:(NSNotification *)notification;
TableView選中正在修改時調用的函數
- (void)tableViewSelectionIsChanging:(NSNotification *)notification;