# NSTabView
[TOC]
***
# 一、xib 简单创建 NSTabView
![tabView](/Users/MelissaShu/macos/tabView.png)
***
## 1、拖拽控件到 xib
在 xib 右下侧控件栏,搜索 tabView,拖拽到 xib面板上,就创建了一个tabView。
tabView 自带两个 NSTabViewItem,就是上方的两个按键;
从控件工具箱拖拽 NSButton、NSImageView 到 tabview 面板上;点击上方 NSTabViewItem,即可切换面板,再次拖拽控件到面板。运行,就可以看到效果。
可以修改右侧的style 属性,来修改 NSTabViewItem 的位置,和边框的样式。对应到代码中的属性为 tabPosition 和 tabViewBorderType。
***
## 2、使用 NSViewController 控制 tabview 的内容显示。
2.1 这里我没有用xib 和 storyboard。我将tabview 连线到xib关联的 controller.
![tabview-xib](/Users/MelissaShu/macos/tabview-xib.png)
2.2 创建两个类 SecViewController、ThirdViewController 继承自 NSViewController,并添加控件到 ViewControlle 的 xib上。
2.3 获取到 tabview 的所有 items,并设置 item.view 为上面两个类的view
```
SecViewController *secVC = [[SecViewController alloc]init];
ThirdViewController *thirdVC = [[ThirdViewController alloc]init];
NSArray *tabItems = self.tabView.tabViewItems;
NSTabViewItem *item0 = tabItems[0];
// [item0.view addSubview:secVC.view]; //无效
[item0 setView:secVC.view]; //注意尺寸,如果在 secVC 的内容超过了 tabView 的尺寸,可能超出的内容不会显示
NSTabViewItem *item1 = tabItems[1];
[item1 setView:thirdVC.view];
```
再次运行就可以看到 tabview 显示的内容分别为 SecViewController、ThirdViewController 的view。
如果你看不到上面类的内容,可能是拖拽控件的位置,超过了 tabview.frame。
***
# 二、纯代码创建 NSTabView
## 1、初始化 tabview
```
NSTabView *tabView = [[NSTabView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)]; //如果尺寸较小,而item长度容纳不下,会被挤出去
//默认是透明色
tabView.delegate = self;
tabView.tabPosition = NSTabPositionLeft; //显示位置:显示在左侧
tabView.tabViewBorderType = NSTabViewBorderTypeBezel;//边框样式:bezel类型边框
[self.view addSubview:tabView];
```
其中 tabPosition 和 tabViewBorderType 的值对应下面枚举
### NSTabPosition
```
typedef NS_ENUM(NSUInteger, NSTabPosition) {
NSTabPositionNone = 0,//无
NSTabPositionTop = 1,//上
NSTabPositionLeft = 2,//左
NSTabPositionBottom = 3,//下
NSTabPositionRight = 4//右
} NS_AVAILABLE_MAC(10_12);
```
------
### NSTabViewBorderType
```
typedef NS_ENUM(NSUInteger, NSTabViewBorderType) {
NSTabViewBorderTypeNone = 0,
NSTabViewBorderTypeLine = 1,
NSTabViewBorderTypeBezel = 2
} NS_AVAILABLE_MAC(10_12);
```
***
### NSTabViewType 过期
使用 tabPosition 和 tabViewBorderType 代替
```
typedef NS_ENUM(NSUInteger, NSTabViewType) {
NSTopTabsBezelBorder = 0, // the default
NSLeftTabsBezelBorder = 1,
NSBottomTabsBezelBorder = 2,
NSRightTabsBezelBorder = 3,
NSNoTabsBezelBorder = 4,
NSNoTabsLineBorder = 5,
NSNoTabsNoBorder = 6
};
```
***
## 2、创建item
可以使用 init 方法创建,再去设置view;
也可以使用 tabViewItemWithViewController 来创建item,并添加
```
SecViewController *secVC = [[SecViewController alloc]init];
ThirdViewController *thirdVC = [[ThirdViewController alloc]init];
NSTabViewItem *item0 = [[NSTabViewItem alloc]init];
[item0 setView:secVC.view];
NSTabViewItem *item1 = [[NSTabViewItem alloc]init];
NSTabViewItem *item2 = [[NSTabViewItem alloc]init];
// NSTabViewItem *item3 = [[NSTabViewItem alloc]init];
NSTabViewItem *item3 = [NSTabViewItem tabViewItemWithViewController:thirdVC];
item0.label = @"item0";
item1.label = @"item1";
item2.label = @"item2";
item3.label = @"item3";
```
NSTabViewItem 继承自 NSObject
### 2.1 初始化方法
```
+ (instancetype)tabViewItemWithViewController:(NSViewController *)viewController NS_AVAILABLE_MAC(10_10);
- (instancetype)initWithIdentifier:(nullable id)identifier;
```
***
### 2.2 常用属性
```
@property (strong, nullable) id identifier;
@property (copy) NSString *label;
@property (nullable, strong) NSView *view;
@property (nullable, strong) NSViewController *viewController
@property (nullable, readonly) NSTabView *tabView;
@property (readonly) NSTabState tabState;
@property (nullable, weak) NSView *initialFirstResponder;
```
添加item(第三步) 后写下如下代码:
```
NSLog(@"\n tabView : %@ \n viewController : %@ \n view : %@ \n thirdVC : %@ \n thirdVC.view : %@ \n initialFirstResponder : %@ ",item3.tabState,item3.tabView,item3.viewController,item3.view,thirdVC,thirdVC.view,item3.initialFirstResponder);
```
打印日志如下:
```
tabView : <NSTabView: 0x100529f30>
viewController : <ThirdViewController: 0x6000000c9450>
view : <NSView: 0x6040001223a0>
thirdVC : <ThirdViewController: 0x6000000c9450>
thirdVC.view : <NSView: 0x6040001223a0>
initialFirstResponder : (null)
```
可见使用 tabViewItemWithViewController 初始化的item
item3.viewController = thirdVC
item3.view = thirdVC.view
***
下面几个属性没用
```
@property (copy) NSColor *color; //过期没用了
@property (nullable, strong) NSImage *image NS_AVAILABLE_MAC(10_10);//有bug 设不上
@property (nullable, copy) NSString *toolTip NS_AVAILABLE_MAC(10_6);//悬停时的提示语
```
***
## 3 添加 item
```
[tabView addTabViewItem:item0];
[tabView addTabViewItem:item1];
```
你可以使用上述方法添加item,但item多的时候,非常冗余。但又没有添加多个的方法。
这时我们可以写一个 NSTabView 的category 来添加多个 item,category 是对现有类方法的扩展。
### 使用category 添加 item
新建 macOS -- Object-C File,填写你的名称,下面选择 Category -- NSTabView,next 即可。
![tabview-category](/Users/MelissaShu/macos/tabview-category.png)
在 .h 和 .m 中写下如下代码
```
#import <Cocoa/Cocoa.h>
@interface NSTabView (pms)
- (void)addItemFromArray:(NSArray *)itemArray;
@end
```
```
#import "NSTabView+pms.h"
@implementation NSTabView (pms)
- (void)addItemFromArray:(NSArray *)itemArray{
for (NSTabViewItem *item in itemArray) {
[self addTabViewItem:item];
}
}
@end
```
回到添加tabview 的控制器,使用下述代码添加完成所有item。
```
[tabView addItemFromArray:@[item0,item1,item2,item3]];
```
***
# 数据源方法
```
//返回行数
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
return 15;
}
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
//获取表格列的标识符
NSString *columnID = tableColumn.identifier;
NSLog(@"columnID : %@ ,row : %d",columnID,row);
NSString *strIdt = @"123";
NSTableCellView *cell = [tableView makeViewWithIdentifier:strIdt owner:self];
if (!cell) {
cell = [[NSTableCellView alloc]init];
cell.identifier = strIdt;
}
cell.wantsLayer = YES;
cell.layer.backgroundColor = [NSColor yellowColor].CGColor;
cell.imageView.image = [NSImage imageNamed:@"swift"];
cell.textField.stringValue = [NSString stringWithFormat:@"cell %ld",(long)row];
return cell;
}
```
# 代理方法 NSTabViewDelegate
记得设置 `tabView.delegate = self;` ,然后在该类申明后添加 NSTabViewDelegate。
```
@interface FirstViewController ()<NSTabViewDelegate>
```
***
代理方法
```
#pragma mark - NSTabViewDelegate
//是否点击
- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem{
NSLog(@"shouldSelectTabViewItem : %@ -- ",tabViewItem.label);
return YES;
}
//即将点击item
- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem{
NSLog(@"willSelectTabViewItem : %@ -- ",tabViewItem.label);
}
//已点击item
- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem{
NSLog(@"didSelectTabViewItem : %@ -- ",tabViewItem.label);
}
//item数量变化(我还没用到)
- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)tabView{
NSLog(@"tabViewDidChangeNumberOfTabViewItems --- ");
}
```
***
# 优质第三方推荐
- SFTabView:https://github.com/shinyfrog/SFTabView
![SFTabView](/Users/MelissaShu/macos/SFTabView.png)
***
# 参考资料
- [天狐](http://www.skyfox.org/author/admin):[Cocoa开发之NSTabView](http://www.skyfox.org/cocoa-nstabview.html)
http://www.skyfox.org/cocoa-nstabview.html