首页 > 其他分享 >Mac开发基础18-NSTableView(一)

Mac开发基础18-NSTableView(一)

时间:2024-08-06 17:05:41浏览次数:11  
标签:return tableView 18 self Mac tableColumn NSTableView row

NSTableView 是 macOS 应用程序中用于显示和管理数据表格的控件。它提供了丰富的 API 和高度自定义的能力,使得开发者可以精细地控制表格的显示和行为。本文将详细介绍 NSTableView 的常见 API 和一些基础技巧,并深入探讨其相关知识。

1. 基本使用

创建和初始化

Objective-C

#import <Cocoa/Cocoa.h>

// 创建并初始化一个 NSTableView 实例
NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300)];

// 创建并初始化一个 NSTableColumn 实例
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"ColumnIdentifier"];
[column setWidth:300]; // 设置列宽

// 为表格视图添加列
[tableView addTableColumn:column];

// 设置表格头标题
[[column headerCell] setStringValue:@"Header Title"];

Swift

import Cocoa

// 创建并初始化一个 NSTableView 实例
let tableView = NSTableView(frame: NSRect(x: 0, y: 0, width: 400, height: 300))

// 创建并初始化一个 NSTableColumn 实例
let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("ColumnIdentifier"))
column.width = 300 // 设置列宽

// 为表格视图添加列
tableView.addTableColumn(column)

// 设置表格头标题
column.headerCell.title = "Header Title"

数据源和委托

NSTableView 依赖数据源 (NSTableViewDataSource) 和委托 (NSTableViewDelegate) 来提供数据和处理用户交互事件。

Objective-C

// 设置数据源和委托
[tableView setDataSource:self];
[tableView setDelegate:self];
// 实现数据源协议
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    return _dataArray.count; // 返回数据源中的行数
}

- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row {
    return _dataArray[row]; // 返回行数据
}
// 实现委托协议
- (nullable NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row {
    NSTextField *textField = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
    if (!textField) {
        textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, tableColumn.width, 20)];
        textField.identifier = tableColumn.identifier;
    }
    textField.stringValue = _dataArray[row];
    return textField;
}

Swift

// 设置数据源和委托
tableView.dataSource = self
tableView.delegate = self
// 实现数据源协议
func numberOfRows(in tableView: NSTableView) -> Int {
    return dataArray.count // 返回数据源中的行数
}

func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
    return dataArray[row] // 返回行数据
}
// 实现委托协议
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let identifier = tableColumn?.identifier ?? NSUserInterfaceItemIdentifier("")
    var textField = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTextField
    if textField == nil {
        textField = NSTextField(frame: NSRect(x: 0, y: 0, width: tableColumn?.width ?? 100, height: 20))
        textField?.identifier = identifier
    }
    textField?.stringValue = dataArray[row]
    return textField
}

2. 编辑和选择

允许选择行

Objective-C

[tableView setAllowsSelection:YES];  // 允许选择行

Swift

tableView.allowsSelection = true  // 允许选择行

允许编辑单元格

Objective-C

- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    return YES;  // 允许编辑单元格
}

Swift

func tableView(_ tableView: NSTableView, shouldEdit tableColumn: NSTableColumn?, row: Int) -> Bool {
    return true  // 允许编辑单元格
}

处理行选择事件

Objective-C

- (void)tableViewSelectionDidChange:(NSNotification *)notification {
    NSInteger selectedRow = [tableView selectedRow];
    if (selectedRow != -1) {
        NSLog(@"Selected row: %ld", (long)selectedRow);  // 处理行选择事件
    }
}

Swift

func tableViewSelectionDidChange(_ notification: Notification) {
    let selectedRow = tableView.selectedRow
    if selectedRow != -1 {
        print("Selected row: \(selectedRow)")  // 处理行选择事件
    }
}

3. 高级用法

自定义单元格

可以通过创建自定义 NSTableCellView 来实现复杂的单元格布局。

Objective-C

@interface CustomTableCellView : NSTableCellView
@property (nonatomic, strong) NSTextField *customTextField;
@end

@implementation CustomTableCellView

- (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        _customTextField = [[NSTextField alloc] initWithFrame:frameRect];
        [self addSubview:_customTextField];
    }
    return self;
}

@end
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    CustomTableCellView *cellView = [tableView makeViewWithIdentifier:@"CustomCell" owner:self];
    if (!cellView) {
        cellView = [[CustomTableCellView alloc] initWithFrame:NSMakeRect(0, 0, tableColumn.width, 20)];
        cellView.identifier = @"CustomCell";
    }
    cellView.customTextField.stringValue = _dataArray[row];
    return cellView;
}

Swift

class CustomTableCellView: NSTableCellView {
    var customTextField: NSTextField?
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        customTextField = NSTextField(frame: frameRect)
        if let customTextField = customTextField {
            addSubview(customTextField)
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("CustomCell"), owner: self) as? CustomTableCellView
    if cellView == nil {
        cellView = CustomTableCellView(frame: NSRect(x: 0, y: 0, width: tableColumn?.width ?? 100, height: 20))
        cellView?.identifier = NSUserInterfaceItemIdentifier("CustomCell")
    }
    cellView?.customTextField?.stringValue = dataArray[row]
    return cellView
}

表头的自定义视图

可以通过提供自定义表头视图来替换默认的表头视图。

Objective-C

- (NSTableHeaderView *)tableView:(NSTableView *)tableView viewForHeaderInSection:(NSInteger)section {
    CustomHeaderView *headerView = [tableView makeViewWithIdentifier:@"CustomHeader" owner:self];
    if (!headerView) {
        headerView = [[CustomHeaderView alloc] initWithFrame:NSMakeRect(0, 0, tableView.frame.size.width, 30)];
        headerView.identifier = @"CustomHeader";
    }
    headerView.title = @"Custom Header";
    return headerView;
}

Swift

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var headerView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("CustomHeader"), owner: self) as? CustomHeaderView
    if headerView == nil {
        headerView = CustomHeaderView(frame: NSRect(x: 0, y: 0, width: tableView.frame.size.width, height: 30))
        headerView?.identifier = NSUserInterfaceItemIdentifier("CustomHeader")
    }
    headerView?.title = "Custom Header"
    return headerView
}

处理拖放操作

可以通过实现 tableView(_:writeRowsWith:to:)tableView(_:acceptDrop:row:dropOperation:) 方法来支持拖放操作。

Objective-C

- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard {
    // 允许拖动的行,并将相关数据写入到剪贴板
    [pboard declareTypes:@[NSPasteboardTypeString] owner:self];
    [pboard setString:[NSString stringWithFormat:@"%ld", rowIndexes.firstIndex] forType:NSPasteboardTypeString];
    return YES;
}

- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id<NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation {
    return NSDragOperationMove; // 指示允许移动操作
}

- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation {
    NSPasteboard *pboard = [info draggingPasteboard];
    NSString *rowString = [pboard stringForType:NSPasteboardTypeString];
    NSInteger draggedRow = [rowString integerValue];
    
    // 交换数据源中的行顺序
    id draggedObject = _dataArray[draggedRow];
    [_dataArray removeObjectAtIndex:draggedRow];
    [_dataArray insertObject:draggedObject atIndex:row];
    [tableView reloadData];
    
    return YES;
}

Swift

func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
    // 允许拖动的行,并将相关数据写入到剪贴板
    pboard.declareTypes([.string], owner: self)
    pboard.setString("\(rowIndexes.first ?? 0)", forType: .string)
    return true
}

func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
    return .move // 指示允许移动操作
}

func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool {
    guard let rowString = info.draggingPasteboard.string(forType: .string),
          let draggedRow = Int(rowString) else {
        return false
    }
    
    // 交换数据源中的行顺序
    let draggedObject = dataArray[draggedRow]
    dataArray.remove(at: draggedRow)
    dataArray.insert(draggedObject, at: row)
    tableView.reloadData()
    
    return true
}

4. 深入探讨

NSTableView 的内部机制

NSTableView 是建立在 NSView 之上的,它通过 NSTableColumn 管理列信息,并使用 rowHeight 属性控制行高。每个单元格作为 NSView 存在,可以是一个简单的 NSTextField,也可以是自定义的 NSTableCellView

数据缓存和复用机制

NSTableView 使用了一种类似于 UITableView 的数据缓存和复用机制。通过 dequeueReusableCell(withIdentifier:) 方法,可以重用已经创建的单元格视图,提高性能。

性能优化策略

  1. 避免过多创建视图:尽量重用现有视图,减少不必要的视图创建。
  2. 接受部分更新:使用 reloadRows(atIndexes:) 方法更新特定行的数据,而不是 reloadData
  3. 异步数据加载:对于大型数据集,可以使用异步加载来提高性能。例如,分页加载或后台加载数据。

总结

NSTableView 是一个强大且灵活的表格控件,通过了解其常见 API 和基础技巧,可以实现基本的表格展示和交互需求。

标签:return,tableView,18,self,Mac,tableColumn,NSTableView,row
From: https://www.cnblogs.com/chglog/p/18345602

相关文章

  • LlamaCoder:一款开源的平替 Claude Artifacts 项目
    LlamaCoder是一个开源项目,旨在提供一种替代ClaudeArtifacts的解决方案。ClaudeArtifacts是一个商业软件,可能包含一些专有技术或特定的功能集,而LlamaCoder则致力于提供类似的功能,但以开源的形式,允许更广泛的社区参与和贡献。由于LlamaCoder是一个假想的开源项目,我将......
  • Mac开发基础16-NSButton(一)
    NSButton是macOS应用中常用的控件之一,用于处理各种按钮操作。它不仅提供了丰富的API来定制按钮的外观和行为,还可以通过不同的配置实现多种类型的按钮,如push按钮、toggle按钮、radio按钮等。1.基本用法创建和初始化Objective-C//创建和初始化一个NSButton实例NSB......
  • Mac开发基础17-NSButton(二)
    NSButton是一个功能强大且灵活多样的控件,除了基本使用和常见API外,还有一些进阶用法和技巧可以提高按钮的可用性和实现细节。在以下内容中,我会详细介绍一些进阶使用技巧,并封装一个常用的工具类来实现自定义的多种按钮类型。进阶使用和技巧1.自定义按钮的外观和行为Objective-C......
  • Mac开发基础13-NSTextView(一)
    NSTextView是macOS应用开发中相当强大的多行文本输入控件。它不仅支持文本输入和显示,还支持富文本、文本编辑、布局管理等功能。常见API和基础技巧初始化NSTextView程序化创建Objective-C//创建一个NSScrollView作为NSTextView的容器,因为NSTextView通常需要带滚动条的......
  • Mac开发基础14-NSTextView(二)
    进阶使用和技巧1.扩展查找和替换功能可以自定义查找和替换功能,包括高亮查找结果、批量替换等。查找并高亮Objective-C-(void)highlightOccurrencesOfString:(NSString*)searchString{//清除之前的高亮效果[textView.layoutManagerremoveTemporaryAttribute:N......
  • Xmind2024支持多平台使用,包括Windows、Mac、iOS、等操作系统
    “Xmind2024”是Xmind公司推出的一款全新的思维导图软件,它集成了多种功能,包括智能导图、AI生成、语音输入等。这款产品旨在帮助用户更高效地整理思路,提高思维能力。让我们来了解一下Xmind2024的特点。它采用了全新的设计风格,界面简洁明了,操作便捷。同时,它还提供了丰富的模板......
  • XMind2024思维导图软件特别版+便携版Mac+win+平板
    大家好!今天我们要聊的是一款神奇的思维工具——Xmind2024。你是否常常感到思维混乱,无法集中注意力,或者在处理复杂问题时感到无从下手?如果你有以上的困扰,那么恭喜你,Xmind2024将为你打开一扇全新的大门。让我们先来看看Xmind2024的特点吧。这款产品最大的亮点在于其强大的思维导......
  • Mac开发基础11-NSTextField(一)
    NSTextField是macOS应用中常用的UI元素之一,它用于显示和输入文本。NSTextField提供了丰富的API来定制和处理用户输入。常见API和技巧1.初始化NSTextField程序化创建Objective-CNSTextField*textField=[[NSTextFieldalloc]initWithFrame:NSMakeRect(0,0,20......
  • Mac开发基础12-NSTextField(二)
    NSTextField是一个功能强大的控件,不仅可以作为简单的文本输入框,还可以实现更多高级功能。例如,支持富文本、实现自定义绘制、处理复杂的输入校验等。进阶使用和技巧1.富文本显示与编辑NSTextField支持富文本,也就是说你可以为文本设置不同的颜色、字体、大小等。设置富文本O......
  • Mac开发基础09-NSViewController(一)
    NSViewController简介NSViewController是macOS应用程序中的核心类,用于管理单个视图层次结构。它提供了对视图生命周期、布局管理和内容更新的控制,并与模型数据和其他控制器进行交互,提供了高效的视图控制和管理机制。基础知识点NSViewController继承自NSResponder,它主要用......