Implementing drag and drop in NSTableView
11,508
Solution 1
Here is an example
#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
Solution 2
You need to declare a custom drag type for your table view and then call registerForDraggedTypes:
with your custom type. Otherwise, as you have noticed, none of these methods will get called.
Solution 3
Drag and Drop NSTableview using core data
Register table-view object for drag and drop:-
[tblCategory registerForDraggedTypes:[NSArray arrayWithObject:@"public.text"]];
Drag and drop Delegate methods:-
- (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;
}
Solution 4
I usually observe this kind of error when I forgot to hook up the dataSource
to the NSTabeView
in IB, i.e. the class implementing the tableView:writeRowsWithIndexes:toPasteboard:
method of the NSTableViewDataSource.
Author by
akhil gupta
Updated on June 04, 2022Comments
-
akhil gupta almost 2 years
Can anyone help me to implement drag and drop in an NSTableView? I used this code below, but these methods are not getting called during execution.
- (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... }
-
akhil gupta almost 13 yearshi thanks for your suggestion. but i don't know how to declare a custom dragtype
-
TheFuquan about 8 yearsThis is a more comprehensive response, thanks for your time.
-
Alex about 7 yearsLink broken "Site Error: Unable to Load Site Preferences; No Preferences Found"