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

Mac开发基础19-NSTableView(二)

时间:2024-08-06 17:28:41浏览次数:15  
标签:identifier tableView 19 self cellView Mac NSTableView row

进阶使用和技巧

1. 单击和双击行事件处理

Objective-C

// 单击行时的处理
- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn {
    NSInteger clickedRow = [tableView clickedRow];
    if (clickedRow >= 0) {
        NSLog(@"Single click on row: %ld", (long)clickedRow); // 处理单击事件
    }
}

// 双击行时的处理
- (void)tableViewDoubleClick:(id)sender {
    NSInteger clickedRow = [tableView clickedRow];
    if (clickedRow >= 0) {
        NSLog(@"Double click on row: %ld", (long)clickedRow); // 处理双击事件
    }
}

// 配置双击事件
- (void)setupDoubleClickEventForTableView:(NSTableView *)tableView {
    [tableView setTarget:self];  // 设置点击事件的目标
    [tableView setDoubleAction:@selector(tableViewDoubleClick:)];  // 设置双击事件处理方法
}

Swift

// 单击行时的处理
func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
    let clickedRow = tableView.clickedRow
    if clickedRow >= 0 {
        print("Single click on row: \(clickedRow)") // 处理单击事件
    }
}

// 双击行时的处理
@objc func tableViewDoubleClick(_ sender: AnyObject) {
    let clickedRow = tableView.clickedRow
    if clickedRow >= 0 {
        print("Double click on row: \(clickedRow)") // 处理双击事件
    }
}

// 配置双击事件
func setupDoubleClickEventForTableView(_ tableView: NSTableView) {
    tableView.target = self  // 设置点击事件的目标
    tableView.doubleAction = #selector(tableViewDoubleClick(_:))  // 设置双击事件处理方法
}

2. 拖动行重新排序

Objective-C

// 开始拖动行时的处理
- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pasteboard {
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
    [pasteboard declareTypes:@[NSPasteboardTypeString] owner:self];
    [pasteboard setData:data 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 *pasteboard = [info draggingPasteboard];
    NSData *data = [pasteboard dataForType:NSPasteboardTypeString];
    NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    
    // 获取拖动的行并重新排序数据源
    NSInteger movingRow = [rowIndexes firstIndex];
    id object = _dataArray[movingRow];
    [_dataArray removeObjectAtIndex:movingRow];
    [_dataArray insertObject:object atIndex:row];
    
    [tableView reloadData]; // 重新加载表格
    return YES;
}

Swift

// 开始拖动行时的处理
func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pasteboard: NSPasteboard) -> Bool {
    let data = NSKeyedArchiver.archivedData(withRootObject: rowIndexes)
    pasteboard.declareTypes([.string], owner: self)
    pasteboard.setData(data, 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 pasteboard = info.draggingPasteboard.data(forType: .string),
          let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: pasteboard) as? IndexSet
    else {
        return false
    }
    
    // 获取拖动的行并重新排序数据源
    let movingRow = rowIndexes.first ?? 0
    let object = dataArray[movingRow]
    dataArray.remove(at: movingRow)
    dataArray.insert(object, at: row)
    
    tableView.reloadData() // 重新加载表格
    return true
}

3. 预加载内容和缓存优化

Objective-C

// 使用内存缓存来优化单元格的创建
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    NSString *identifier = [tableColumn identifier];
    NSTableCellView *cellView = [tableView makeViewWithIdentifier:identifier owner:self];
    
    if (!cellView) {
        cellView = [[NSTableCellView alloc] init];
        cellView.identifier = identifier;
    }
    
    // 配置单元格的内容
    cellView.textField.stringValue = _dataArray[row];
    return cellView;
}

Swift

// 使用内存缓存来优化单元格的创建
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let identifier = tableColumn?.identifier ?? NSUserInterfaceItemIdentifier(rawValue: "")
    var cellView = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView
    
    if cellView == nil {
        cellView = NSTableCellView()
        cellView?.identifier = identifier
    }
    
    // 配置单元格的内容
    cellView?.textField?.stringValue = dataArray[row]
    return cellView
}

4. 自定义表头视图和排序功能

Objective-C

#import "CustomHeaderView.h"
@implementation CustomHeaderView
// 自定义表头视图,可以加入按钮和其他控件
@end

@interface MyViewController ()
// 记录当前的排序键和排序方向
@property (nonatomic, strong) NSString *sortedColumnIdentifier;
@property (nonatomic, assign) BOOL isAscending;
@end

@implementation MyViewController

- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn {
    NSString *identifier = tableColumn.identifier;
    if ([self.sortedColumnIdentifier isEqualToString:identifier]) {
        self.isAscending = !self.isAscending; // 切换排序方向
    } else {
        self.sortedColumnIdentifier = identifier;
        self.isAscending = YES; // 默认升序
    }
    
    // 按照列标识符排序数据源
    [self.dataArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        if (self.isAscending) {
            return [[obj1 valueForKey:identifier] compare:[obj2 valueForKey:identifier]];
        } else {
            return [[obj2 valueForKey:identifier] compare:[obj1 valueForKey:identifier]];
        }
    }];
    
    [tableView reloadData];
}

Swift

import Cocoa

class CustomHeaderView: NSView {
    // 自定义表头视图,可以加入按钮和其他控件
}

class MyViewController: NSViewController {
    // 记录当前的排序键和排序方向
    var sortedColumnIdentifier: String?
    var isAscending: Bool = true

    func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
        let identifier = tableColumn.identifier.rawValue
        if sortedColumnIdentifier == identifier {
            isAscending.toggle() // 切换排序方向
        } else {
            sortedColumnIdentifier = identifier
            isAscending = true // 默认升序
        }
        
        // 按照列标识符排序数据源
        dataArray.sort {
            if isAscending {
                return ($0[identifier] as? String ?? "") < ($1[identifier] as? String ?? "")
            } else {
                return ($0[identifier] as? String ?? "") > ($1[identifier] as? String ?? "")
            }
        }
        
        tableView.reloadData()
    }
}

5. 单元格内嵌按钮事件处理

Objective-C

// 自定义单元格视图,带按钮
@interface CustomButtonCellView : NSTableCellView
@property (nonatomic, strong) NSButton *actionButton;
@end

@implementation CustomButtonCellView
- (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        _actionButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 50, 20)];
        _actionButton.title = @"Click";
        _actionButton.target = self;
        _actionButton.action = @selector(buttonClicked:);
        [self addSubview:_actionButton];
    }
    return self;
}

// 按钮事件处理
- (void)buttonClicked:(id)sender {
    NSLog(@"Button in row %ld clicked", self.row);
}
@end

// 在视图控制器中返回自定义单元格
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    CustomButtonCellView *cellView = [tableView makeViewWithIdentifier:@"CustomButtonCell" owner:self];
    if (!cellView) {
        cellView = [[CustomButtonCellView alloc] initWithFrame:NSMakeRect(0, 0, tableColumn.width, 20)];
        cellView.identifier = @"CustomButtonCell";
    }
    cellView.row = row;
    return cellView;
}

Swift

// 自定义单元格视图,带按钮
class CustomButtonCellView: NSTableCellView {
    var actionButton: NSButton!

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        actionButton = NSButton(frame: NSRect(x: 0, y: 0, width: 50, height: 20))
        actionButton.title = "Click"
        actionButton.target = self
        actionButton.action = #selector(buttonClicked(_:))
        addSubview(actionButton)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // 按钮事件处理
    @objc func buttonClicked(_ sender: Any) {
        print("Button in row \(self.row ?? -1) clicked")
    }
}

// 在视图控制器中返回自定义单元格
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("CustomButtonCell"), owner: self) as? CustomButtonCellView
    if cellView == nil {
        cellView = CustomButtonCellView(frame: NSRect(x: 0, y: 0, width: tableColumn?.width ?? 100, height: 20))
        cellView?.identifier = NSUserInterfaceItemIdentifier("CustomButtonCell")
    }
    cellView?.row = row
    return cellView
}

封装工具类

为了更方便地使用 NSTableView,我们可以封装一个工具类,提供常见功能的高层接口。

Objective-C

#import <Cocoa/Cocoa.h>

@interface NSTableViewHelper : NSObject

+ (NSTableView *)createTableViewWithColumns:(NSArray<NSString *> *)columnIdentifiers target:(id)target;
+ (void)setupDragAndDropForTableView:(NSTableView *)tableView;
+ (void)enableDoubleClickEventForTableView:(NSTableView *)tableView target:(id)target action:(SEL)action;

@end

@implementation NSTableViewHelper

+ (NSTableView *)createTableViewWithColumns:(NSArray<NSString *> *)columnIdentifiers target:(id)target {
    NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300)];
    for (NSString *identifier in columnIdentifiers) {
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:identifier];
        column.headerCell.title = identifier;
        column.width = 100;
        [tableView addTableColumn:column];
    }
    tableView.dataSource = target;
    tableView.delegate = target;
    return tableView;
}

+ (void)setupDragAndDropForTableView:(NSTableView *)tableView {
    [tableView registerForDraggedTypes:@[NSPasteboardTypeString]];
    tableView.draggingSourceOperationMask = NSDragOperationEvery;
}

+ (void)enableDoubleClickEventForTableView:(NSTableView *)tableView target:(id)target action:(SEL)action {
    [tableView setTarget:target];
    [tableView setDoubleAction:action];
}

@end

Swift

import Cocoa

class NSTableViewHelper {
    
    // 创建表格视图并添加列
    static func createTableView(columnIdentifiers: [String], target: NSObject) -> NSTableView {
        let tableView = NSTableView(frame: NSRect(x: 0, y: 0, width: 400, height: 300))
        for identifier in columnIdentifiers {
            let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: identifier))
            column.headerCell.title = identifier
            column.width = 100
            tableView.addTableColumn(column)
        }
        tableView.dataSource = target as? NSTableViewDataSource
        tableView.delegate = target as? NSTableViewDelegate
        return tableView
    }
    
    // 配置拖放功能
    static func setupDragAndDrop(for tableView: NSTableView) {
        tableView.registerForDraggedTypes([.string])
        tableView.draggingSourceOperationMask = .every
    }
    
    // 启用双击事件处理
    static func enableDoubleClickEvent(for tableView: NSTableView, target: AnyObject, action: Selector) {
        tableView.target = target
        tableView.doubleAction = action
    }
}

使用示例

Objective-C

// 创建表格视图
NSTableView *tableView = [NSTableViewHelper createTableViewWithColumns:@[@"Column1", @"Column2"] target:self];

// 配置拖放功能
[NSTableViewHelper setupDragAndDropForTableView:tableView];

// 启用双击事件
[NSTableViewHelper enableDoubleClickEventForTableView:tableView target:self action:@selector(tableViewDoubleClick:)];

Swift

// 创建表格视图
let tableView = NSTableViewHelper.createTableView(columnIdentifiers: ["Column1", "Column2"], target: self)

// 配置拖放功能
NSTableViewHelper.setupDragAndDrop(for: tableView)

// 启用双击事件
NSTableViewHelper.enableDoubleClickEvent(for: tableView, target: self, action: #selector(tableViewDoubleClick(_:)))

标签:identifier,tableView,19,self,cellView,Mac,NSTableView,row
From: https://www.cnblogs.com/chglog/p/18345641

相关文章

  • Mac开发基础18-NSTableView(一)
    NSTableView是macOS应用程序中用于显示和管理数据表格的控件。它提供了丰富的API和高度自定义的能力,使得开发者可以精细地控制表格的显示和行为。本文将详细介绍NSTableView的常见API和一些基础技巧,并深入探讨其相关知识。1.基本使用创建和初始化Objective-C#import......
  • 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......