macOS开发之NSTableView的应用详解(一)

简介: macOS开发之NSTableView的应用详解

一、引言


   和iOS开发中的UITableView有很大差别,NSTableView并非是一个可滚动的列表视图,其是一个不可滚动、支持多列多行的原始列表视图。若要使NSTableView支持滚动,通常会将其嵌套入NSScrollView控件中。与UITableView类似,NSTableView的数据也是用过DataSource代理来提供,通过Delegate代理来进行表格视图的定制化。在OS X v10.6版本之前,NSTableView中行数据载体视图必须是NSCell的子类,之后版本的OS X支持开发者创建基于View的TableView视图,同样也支持基于Cell的TabelView视图,在开发者,我们可以根据实际需求选择。


二、构建一个简单的列表视图


   首先新建一个测试工程,在ViewController.m文件中编写如下代码:


#import "ViewController.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"];

   [_tableView addTableColumn:column];

   _tableView.delegate = self;

   _tableView.dataSource = self;

   [_tableView reloadData];

   scrollView.contentView.documentView = _tableView;

}


-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{

   return _dataArray.count;

}


-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{

   return _dataArray[row];

}


@end

运行工程效果如下图:




这是一个最简单的TableView示例,但是细读代码,麻雀虽小五脏俱全。首先NSTableView中的列是由NSTableColumn类描述的。一个列表可以有多个列。也正如前面所说,numberOfRowsInTableView方法为数据源代理必须实现的方法,其中需要返回列表的行数。objectValueForTableColumn方法则是基于Cell的TableView必须实现的方法,其中需要返回每个列表行所填充的数据。


三、关于NSTableColume的探究


   NSTableColume简单理解就是一列,其中可以进行此列样式的相关设置,NSTableColumn类中常用属性解析如下:


//初始化方法,指定一个列ID

- (instancetype)initWithIdentifier:(NSString *)identifier;

//与此列关联的ID

@property (copy) NSString *identifier;

//关联的TableView

@property (nullable, assign) NSTableView *tableView;

//设置列宽度

@property CGFloat width;

//设置最小列宽度

@property CGFloat minWidth;

//设置最大列宽度

@property CGFloat maxWidth;

//设置类标题

@property (copy) NSString *title;

/*

列标题视图 开发者可以对其进行修改

需要注意,NSTableHeaderCell是继承自NSTextFieldCell

*/

@property (strong) __kindof NSTableHeaderCell *headerCell;

//设置此列是否可以进行编辑

@property (getter=isEditable) BOOL editable;

//进行列尺寸的调整 以列标题视图的宽度为标准

- (void)sizeToFit;

//提供了这个属性,会在列标题那里显示一个排序按钮 点击列标题后可以进行排序操作(会回调相关协议方法)

@property (nullable, copy) NSSortDescriptor *sortDescriptorPrototype;

//设置列尺寸的调整模式 枚举如下

/*

typedef NS_OPTIONS(NSUInteger, NSTableColumnResizingOptions) {

   NSTableColumnNoResizing = 0, //不允许进行宽度调整

   //详见NSTabelView的columnAutoresizingStyle属性

   NSTableColumnAutoresizingMask = ( 1 << 0 ), //使用tableView的column调整策略

   NSTableColumnUserResizingMask = ( 1 << 1 ), //允许用户进行尺寸调整

};

*/

@property NSTableColumnResizingOptions resizingMask;

//设置列头的提示标题 当鼠标悬停在类标题上时  会显示此提示

@property (nullable, copy) NSString *headerToolTip;

//设置此列是否隐藏

@property (getter=isHidden) BOOL hidden;

//设置此列所有行的数据载体视图 如果不设置 默认为NSTextFieldCell

@property (strong) id dataCell;

//为TableView列表提供数据载体视图

- (id)dataCellForRow:(NSInteger)row;

四、Cell-Base:基于Cell的TableView视图


   Cell-Base是OS X早起版本中常用的构造TabelView的方式,其中每一行的数据载体都必须是NSCell的子类。如本文开头的示例代码,Cell-Base的TableView必须实现的两个协议方法是numberOfRowsInTableView和objectValueForTableColumn方法,第一个方法设置列表行数,第2个方法设置每个数据载体对应的具体数据。需要注意,如果只实现这两个方法,则NSTableView会自动从列对象NSTableColume中取具体的行视图,通过dataCellForRow方法。当objectValueForTableColumn方法将每个行具体的数据返回后,会调用cell的setObjectValue方法(因此如果要自定义cell,必须实现这个方法)。如果我们要对Cell的渲染进行一些定制,可以在如下方法中实现:


//将要渲染cell调用的方法 开发者可以拿到cell对象做定制

- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;

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


//返回自定义的Cell实例

/*

需要注意,这个方法在第一次调用的时候 tableColumu对象是nil 如果这时返回了Cell,则此Cell宽度会覆盖整个列表

在使用时要多加注意

*/

- (nullable NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;

其他方法的实例代码如下:


#import "ViewController.h"

#import "MyCell.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;

//    column.dataCell = [[NSButtonCell alloc]initTextCell:@""];

   [_tableView addTableColumn:column];

   [_tableView addTableColumn:column2];

   _tableView.delegate = self;

   _tableView.dataSource = self;

   scrollView.contentView.documentView = _tableView;

}


//设置行数 通用

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{

   return _dataArray.count;

}

//绑定数据

-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{

   return _dataArray[row];

}

//用户编辑列表

- (void)tableView:(NSTableView *)tableView setObjectValue:(nullable id)object forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   NSLog(@"%@",object);

   _dataArray[row] = object;

}

//cell-base的cell展示前调用 可以进行自定制

- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   NSTextFieldCell * _cell = cell;

  _cell.textColor = [NSColor redColor];

}

//设置是否可以进行编辑

- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   return YES;

}

//设置鼠标悬停在cell上显示的提示文本

- (NSString *)tableView:(NSTableView *)tableView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation{

   return @"tip";

}

//当列表长度无法展示完整某行数据时 当鼠标悬停在此行上 是否扩展显示

- (BOOL)tableView:(NSTableView *)tableView shouldShowCellExpansionForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   return YES;

}

//设置cell的交互能力

/*

如果返回YES,则Cell的交互能力会变强,例如NSButtonCell的点击将会调用- (void)tableView:(NSTableView *)tableView setObjectValue方法

*/

- (BOOL)tableView:(NSTableView *)tableView shouldTrackCell:(NSCell *)cell forTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   return YES;

}

//自定义cell

- (nullable NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row{

   if (tableColumn!=nil) {

       MyCell * cell = [[MyCell alloc]init];

       return cell;

   }

   return nil;

 

}

-(CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row{

   return 30;

}

//排序回调函数

-(void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors{

   NSLog(@"%@",oldDescriptors[0]);

}


@end

目录
相关文章
|
1月前
|
安全 前端开发 iOS开发
揭秘 electron-builder:macOS 应用打包背后到底发生了什么?
本文详细介绍了 Electron 应用在 macOS 平台上的打包流程,涵盖配置文件、打包步骤、签名及 notarization 等关键环节。通过剖析 `electron-builder` 的源码,展示了如何处理多架构应用、执行签名,并解决常见问题。适合希望深入了解 macOS 打包细节的开发者。
41 2
|
6月前
|
关系型数据库 MySQL iOS开发
macOS Catalina(10.15)如何访问iPhone(Ipad)的应用文档文件
macOS Catalina(10.15)如何访问iPhone(Ipad)的应用文档文件
201 0
|
6月前
|
Web App开发 iOS开发 MacOS
解决macOS 应用安装在下载目录时遇到的 vscode 掉登录和应用无法随机启动的问题
解决macOS 应用安装在下载目录时遇到的 vscode 掉登录和应用无法随机启动的问题
143 0
|
监控 机器人 程序员
【小工具】一键隐藏/显示MacOS的应用图标
【小工具】一键隐藏/显示MacOS的应用图标
|
iOS开发 MacOS
全网首发:(解决办法)MAC OS Xcode给应用设置沙箱(Enable App Sandbox)之后,运行报错Illegal instruction: 4
全网首发:(解决办法)MAC OS Xcode给应用设置沙箱(Enable App Sandbox)之后,运行报错Illegal instruction: 4
752 0
全网首发:(解决办法)MAC OS Xcode给应用设置沙箱(Enable App Sandbox)之后,运行报错Illegal instruction: 4
|
Dart 安全 IDE
Flutter Web实战项目打造真正跨平台应用(windows,android,ios,linux,macos,web)
Flutter Web项目 Flutter 最近发布了 Flutter V2.5.1,其性能得到了很大提升,支持 Web、macOS、Android 和 iOS。 这就是为什么今天我们使用在 Web、macOS 应用、Android 和 iOS 应用上运行的 flutter 创建响应式博客主题。 此外,我们创建了一个具有自定义悬停动画的动画网络菜单。 最后,您将学习如何使用 Flutter 制作响应式应用程序。
586 0
Flutter Web实战项目打造真正跨平台应用(windows,android,ios,linux,macos,web)
|
Web App开发 Dart 安全
flutter制作博客展示平台,现已支持 Web、macOS 应用、Android 和 iOS
Flutter Blog Theme using Flutter | Web, macOS, Android, iOS Flutter 最近发布了 Flutter V2.5.1,其性能得到了很大提升,支持 Web、macOS、Android 和 iOS。 这就是为什么今天我们使用在 Web、macOS 应用、Android 和 iOS 应用上运行的 flutter 创建响应式博客主题。 此外,我们创建了一个具有自定义悬停动画的动画网络菜单。 最后,您将学习如何使用 Flutter 制作响应式应用程序。
382 0
flutter制作博客展示平台,现已支持 Web、macOS 应用、Android 和 iOS
|
Shell 开发工具 Android开发
如何在MacOS上创建第一个iOS Flutter应用
1.安装Flutter 2.设置iOS模拟器 3.在Flutter中创建一个Hello World应用
174 0
如何在MacOS上创建第一个iOS Flutter应用
|
iOS开发 MacOS
MACOS,应用签名后就崩溃?
MACOS,应用签名后就崩溃?
152 0
|
iOS开发 MacOS
macOS开发之NSTableView的应用详解(三)
macOS开发之NSTableView的应用详解
539 0