在 NSTableView 中实现拖放
Posted
技术标签:
【中文标题】在 NSTableView 中实现拖放【英文标题】:Implementing drag and drop in NSTableView 【发布时间】:2011-08-22 06:29:32 【问题描述】:谁能帮我?我在下面使用了这段代码,但这些方法在执行期间没有被调用。
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
// Copy the row numbers to the pasteboard.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:@".gif"] owner:self];
[pboard setData:data forType:@".gif"];
return YES;
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)op
// Add code here to validate the drop
if (row > [ m_imageArray count])
return NSDragOperationNone;
if (nil == [info draggingSource]) // From other application
return NSDragOperationNone;
else if (self == [info draggingSource]) // From self
return NSDragOperationNone;
else // From other documents
[tv setDropRow: row dropOperation: NSTableViewDropAbove];
return NSDragOperationCopy;
NSLog(@"validate Drop");
return NSDragOperationCopy;
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
NSPasteboard* pboard = [info draggingPasteboard];
NSData* rowData = [pboard dataForType:@".gif"];
NSIndexSet* rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];
NSInteger dragRow = [rowIndexes firstIndex];
// Move the specified row to its new location...
【问题讨论】:
【参考方案1】:这是一个例子
#import "TableViewController.h"
#import "Person.h"
#define MyDataType @"MyDataType"
@implementation TableViewController
NSMutableArray *list;
NSInteger sourceIndex;
@synthesize tableView;
-(void)awakeFromNib
[tableView registerForDraggedTypes:[NSArray arrayWithObjects:MyDataType, nil]];
list = [[NSMutableArray alloc] init];
Person *person = [[Person alloc] initWithName:@"Newton" age:64];
[list addObject:person];
person = [[Person alloc] initWithName:@"Archimedes" age:74];
[list addObject:person];
person = [[Person alloc] initWithName:@"Euler" age:44];
[list addObject:person];
person = [[Person alloc] initWithName:@"Poincare" age:24];
[list addObject:person];
person = [[Person alloc] initWithName:@"Gauss" age:34];
[list addObject:person];
-(void)reArrange:(NSMutableArray *)array sourceNum:(NSInteger)sourceNum destNum:(NSInteger)destNum
Person *person = list[sourceNum];
[list insertObject:person atIndex:destNum];
if (sourceNum < destNum)
[list removeObjectAtIndex:sourceNum];
else
[list removeObjectAtIndex:sourceNum+1];
[tableView reloadData];
#pragma mark - Table
// how many rows are there in the table?
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tv
return list.count;
// What object should I show in a particular cell?
-(id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
Person *person = list[row];
NSString *identifier = [tableColumn identifier];
return [person valueForKey:identifier];
// Should I accept the drag with the rows specified by rowIndexes? If YES then place the data on the provided paste board.
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:MyDataType] owner:self];
[pboard setData:data forType:MyDataType];
sourceIndex = [rowIndexes firstIndex];
return YES;
// What kind of drag operation should I perform?
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)op
return op == NSTableViewDropAbove; // Specifies that the drop should occur above the specified row.
// The mouse button was released over a row in the table view, should I accept the drop?
- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id )info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)op
[self reArrange:list sourceNum:sourceIndex destNum:row]; // let the source array reflect the change
return YES;
@end
【讨论】:
这是一个更全面的回复,感谢您的宝贵时间。【参考方案2】:您需要为您的表格视图声明一个自定义拖动类型,然后使用您的自定义类型调用registerForDraggedTypes:
。否则,正如您所注意到的,这些方法都不会被调用。
【讨论】:
您好,感谢您的建议。但我不知道如何声明自定义拖动类型【参考方案3】:使用核心数据拖放 NSTableview
为拖放注册表格视图对象:-
[tblCategory registerForDraggedTypes:[NSArray arrayWithObject:@"public.text"]];
拖放委托方法:-
- (id <NSPasteboardWriting>)tableView:(NSTableView *)tableView pasteboardWriterForRow:(NSInteger)row
Category *category = (Category *)[self.arrCategoryList objectAtIndex:row];
NSString *identifier = category.categoryname;
NSPasteboardItem *pboardItem = [[NSPasteboardItem alloc] init];
[pboardItem setString:identifier forType: @"public.text"];
return pboardItem;
- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation
if(dropOperation == NSTableViewDropOn)
NSPasteboard *p = [info draggingPasteboard];
NSString *title = [p stringForType:@"public.text"];
Category* category ;
NSInteger srcIndex;
for (srcIndex = 0; srcIndex < [_arrCategoryList count]; srcIndex++)
category = [_arrCategoryList objectAtIndex:srcIndex];
if ([category.categoryname isEqualToString:title])
break;
category = nil;
if(!category)
// Not found
return NO;
[_arrCategoryList removeObjectAtIndex:srcIndex];
[_arrCategoryList insertObject:category atIndex:row];
[tblCategory reloadData];
return NSDragOperationMove;
return NSDragOperationNone;
- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation
return YES;
【讨论】:
【参考方案4】:当我忘记将dataSource
连接到IB中的NSTabeView
时,我通常会观察到这种错误,即实现NSTableViewDataSource的tableView:writeRowsWithIndexes:toPasteboard:
方法的类。
【讨论】:
【参考方案5】:您可以为 NSMutableArray 或 NSMutableDictionary 或任何其他对象注册 draggedTypes。以下代码 sn-p 用于 NSMutableArray。
[tableView registerForDraggedTypes:[NSArray arrayWithObject:@"NSMutableArray"] ];
【讨论】:
【参考方案6】:你需要在awakFromnib
中声明一个registerForDraggedTypes
方法
像这样。
[table_view registerForDraggedTypes:[NSArray arrayWithObjects:BasicTableViewDragAndDropDataType, nil]];
【讨论】:
【参考方案7】:我不得不推荐这篇出色的 Red Sweater 博文
http://www.red-sweater.com/blog/274/a-moveable-beast
它提供了一个 NSArrayController 子类,它可以对表格项进行拖放重新排序,如果你想支持用你的对象拖到表格视图之外,我们刚刚写了一个简洁的补充那个班级:
http://www.rwe-uk.com/blog/comments/nstableview_drag_and_drop_with_bindings_and_nsarraycontroller
它建立在原始帖子的基础上
【讨论】:
链接损坏“站点错误:无法加载站点首选项;未找到首选项”以上是关于在 NSTableView 中实现拖放的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 phonegap angular js 项目中实现拖放?