【问题标题】:Drag & Drop Reordering in NSTableView of CoreData object doesn't work在 CoreData 对象的 NSTableView 中拖放重新排序不起作用
【发布时间】:2012-10-22 07:08:22
【问题描述】:

我正在尝试实现一个简单的表,我可以在其中将对象父对象放入用户可定义的顺序中。我将 parentTableView 绑定到 parentArrayController 并将 sortDescriptor 设置为键“order”,该表按“order”键的顺序显示父实体,一切正常。 如果我尝试将一行拖放到新位置,则会在该行发生崩溃,将拖动的对象插入或添加到新位置:

[self.parentArrayController insertObjects:draggedObjects atArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, [draggedObjects count])]];

或 [self.parentArrayController addObjects:dragObjects];

我做错了什么?

这是tableviewdelegate的代码:

@implementation parentTableViewDelegate

@synthesize parentTableView;
@synthesize parentArrayController;

-(id)init{
    if (self = [super init]) {
        self.parentSortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES]];
    }
    return self;
}
- (void)awakeFromNib {
    [super awakeFromNib];
    // user interface preparation code

    [parentTableView registerForDraggedTypes:[NSArray arrayWithObject:[self.parentArrayController entityName]]];
    [parentTableView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES];
}

#pragma mark -
#pragma mark NSTableViewDataSource

- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pasteboard {
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
    [pasteboard declareTypes:[NSArray arrayWithObject:[self.parentArrayController entityName]] owner:self];
    [pasteboard setData:data forType:[self.parentArrayController entityName]];
    return YES;
}

- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op {
    if ([info draggingSource] == parentTableView) {
        if (op == NSTableViewDropOn)
            [tv setDropRow:row dropOperation:NSTableViewDropAbove];
            return NSDragOperationMove;
    } else {
        return NSDragOperationNone;
    }
}

- (BOOL)tableView:(NSTableView *)aTableView
   acceptDrop:(id <NSDraggingInfo>)info
          row:(int)row
dropOperation:(NSTableViewDropOperation)operation {

    // Get object indexes from paste board
    NSData *data = [[info draggingPasteboard] dataForType:[self.parentArrayController entityName]];
    NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    if (!rowIndexes) return NO;

    if (aTableView == self.parentTableView) {
        if ([info draggingSource] == self.parentTableView) {

            NSMutableArray *draggedObjects = [NSMutableArray array];
            [draggedObjects addObject:[[self.parentArrayController arrangedObjects] objectsAtIndexes:rowIndexes]];

            [self.parentArrayController  removeObjectsAtArrangedObjectIndexes:rowIndexes];

            // Insert dragged objects at row
            if (row < [[self.parentArrayController arrangedObjects]count]) {
                [self.parentArrayController insertObjects:draggedObjects atArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, [draggedObjects count])]];
            }
            else {
                [self.parentArrayController addObjects:draggedObjects];
            }

            // Re-order objects
             int    i;
             for (i = 0; i < [[self.parentArrayController arrangedObjects] count]; i++) {
                 [[[self.parentArrayController arrangedObjects] objectAtIndex:i] setValue:[NSNumber numberWithInt:i] forKey:@"order"];
         }

            [self.parentArrayController rearrangeObjects];
            return YES;
        }
    }
    return NO;
}


@end

这是崩溃:

[<__NSArrayI 0x101b197b0> addObserver:forKeyPath:options:context:] is not supported. Key path: order
2012-10-22 08:52:40.630 OrderedSetTest[29950:303] (
0   CoreFoundation                      0x00007fff89e570a6 __exceptionPreprocess + 198
1   libobjc.A.dylib                     0x00007fff8dfa33f0 objc_exception_throw + 43
2   CoreFoundation                      0x00007fff89e56e7c +[NSException raise:format:] + 204
3   Foundation                          0x00007fff8f0f7287 -[NSArray(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] + 76
4   AppKit                              0x00007fff8c622eea -[_NSModelObservingTracker _registerOrUnregister:observerNotificationsForModelObject:] + 200
5   AppKit                              0x00007fff8c622c18 -[_NSModelObservingTracker startObservingModelObjectAtReferenceIndex:] + 177
6   AppKit                              0x00007fff8c70df7d -[NSArrayController _insertObject:atArrangedObjectIndex:objectHandler:] + 593
7   OrderedSetTest                      0x0000000100004bbf -[parentTableViewDelegate tableView:acceptDrop:row:dropOperation:] + 1263
8   AppKit                              0x00007fff8c9baa0e -[NSTableView performDragOperation:] + 215
9   AppKit                              0x00007fff8c8079bf NSCoreDragReceiveMessageProc + 1651
10  HIServices                          0x00007fff8b82046a DoMultipartDropMessage + 301
11  HIServices                          0x00007fff8b820135 DoDropMessage + 49
12  HIServices                          0x00007fff8b8200d7 SendDropMessage + 41
13  HIServices                          0x00007fff8b8237c8 DragInApplication + 654
14  HIServices                          0x00007fff8b822c69 CoreDragStartDragging + 519
15  AppKit                              0x00007fff8c808190 -[NSCoreDragManager _dragUntilMouseUp:accepted:] + 881
16  AppKit                              0x00007fff8c8094ba -[NSCoreDragManager dragImage:fromWindow:at:offset:event:pasteboard:source:slideBack:] + 1455
17  AppKit                              0x00007fff8cab9040 -[NSWindow(NSDrag) dragImage:at:offset:event:pasteboard:source:slideBack:] + 133
18  AppKit                              0x00007fff8c9b91e0 -[NSTableView _doImageDragUsingRowsWithIndexes:event:pasteboard:source:slideBack:startRow:] + 570
19  AppKit                              0x00007fff8c9ba11d -[NSTableView _performClassicDragOfIndexes:hitRow:event:] + 358
20  AppKit                              0x00007fff8c9ba391 -[NSTableView _performDragFromMouseDown:] + 509
21  AppKit                              0x00007fff8c9ac4b2 -[NSTableView mouseDown:] + 707
22  AppKit                              0x00007fff8c59b60e -[NSWindow sendEvent:] + 6853
23  AppKit                              0x00007fff8c597744 -[NSApplication sendEvent:] + 5761
24  AppKit                              0x00007fff8c4ad2fa -[NSApplication run] + 636
25  AppKit                              0x00007fff8c451cb6 NSApplicationMain + 869
26  OrderedSetTest                      0x0000000100001da2 main + 34
27  OrderedSetTest                      0x0000000100001d74 start + 52

【问题讨论】:

    标签: core-data drag-and-drop nstableview


    【解决方案1】:

    问题是,arrayController 的排列对象是代理对象,我必须从上下文中检索托管对象

    工作代码如下:

    #import "GFParentTableViewDelegate.h"
    
    @implementation GFParentTableViewDelegate
    
    -(id)init{
        if (self = [super init]) {
            self.parentSortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES]];
        }
        return self;
    }
    
    - (void)awakeFromNib {
        [super awakeFromNib];
    
        [self.parentTableView registerForDraggedTypes:[NSArray arrayWithObject:[self.parentArrayController entityName]]];
        [self.parentTableView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES];
    }
    
    #pragma mark -
    #pragma mark NSTableViewDataSource
    
    - (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard{
        // Get array controller
        NSDictionary *bindingInfo = [tableView infoForBinding:NSContentBinding];
        NSArrayController *arrayController = [bindingInfo valueForKey:NSObservedObjectKey];
    
        if (!arrayController) {
            return NO;
        }
        [pboard declareTypes:[NSArray arrayWithObject:[arrayController entityName]] owner:self];
    
        // Collect URI representation of managed objects
        NSMutableArray *objectURIs = [NSMutableArray array];
        for (id objProxy in [[arrayController arrangedObjects] objectsAtIndexes:rowIndexes]) {
            [objectURIs addObject:[[objProxy objectID] URIRepresentation]];
        }
    
        // Set them to paste board
        [pboard setData:[NSArchiver archivedDataWithRootObject:objectURIs] forType:[arrayController entityName]];
         NSLog(@"Wrote %ld objects of type: %@ to Pasteboard",[objectURIs count],[arrayController entityName]);
         return YES;
    }
    
    - (NSDragOperation)tableView:(NSTableView*)tableView
                    validateDrop:(id <NSDraggingInfo>)info
                     proposedRow:(NSInteger)row
           proposedDropOperation:(NSTableViewDropOperation)dropOperation {
    
        if ([info draggingSource] == self.parentTableView) {
            if (dropOperation == NSTableViewDropOn){
                [tableView setDropRow:row dropOperation:NSTableViewDropAbove];
            }
            return NSDragOperationMove;
        } else {
            return NSDragOperationNone;
        }
    }
    
    - (BOOL)tableView:(NSTableView *)tableView
           acceptDrop:(id <NSDraggingInfo>)info
                  row:(NSInteger)row
        dropOperation:(NSTableViewDropOperation)operation {
    
        // Get array controller
        NSDictionary *bindingInfo = [tableView infoForBinding:@"content"];
        NSArrayController *arrayController = [bindingInfo valueForKey:NSObservedObjectKey];
    
        // Get object URIs from paste board
        NSData *data = [[info draggingPasteboard] dataForType:[arrayController entityName]];
        NSArray *objectURIs = [NSUnarchiver unarchiveObjectWithData:data];
    
        if (!objectURIs) return NO;
    
        // Get managed object context and persistent store coordinator
        NSManagedObjectContext *context = [[NSApp delegate] managedObjectContext];
        NSPersistentStoreCoordinator *coordinator = [context persistentStoreCoordinator];
    
        // Collect manged objects with URIs
        NSMutableArray *draggedObjects = [NSMutableArray array];
    
        for (NSURL* objectURI in objectURIs) {
            // Get managed object
            NSManagedObjectID*  objectID;
            NSManagedObject*    object;
            objectID = [coordinator managedObjectIDForURIRepresentation:objectURI];
            object = [context objectWithID:objectID];
            if (!object) continue;
    
            [draggedObjects addObject:object];
        }
    
        // Get managed objects
        NSMutableArray *allObjects = [NSMutableArray arrayWithArray:[arrayController arrangedObjects]];;
    
        if (!allObjects || [allObjects count] == 0) return NO;
    
        // Replace dragged objects with null objects as placeholder to prevent old order
        for (NSManagedObject *obj in draggedObjects) {
            NSUInteger index = [allOobjects indexOfObject:obj];
            if (index == NSNotFound) {
                continue;
            }
            [allObjects replaceObjectAtIndex:index withObject:[NSNull null]];
        }
    
        // Insert dragged objects at row
        if (row < [allObjects count]) {
            [allObjects insertObjects:draggedObjects atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, [draggedObjects count])]];
        }
        else {
            [allObjects addObjectsFromArray:draggedObjects];
        }
    
        // Remove old null objects
        [allObjects removeObject:[NSNull null]];
    
        // Re-order objects
         int    i;
         for (i = 0; i < [allObjects count]; i++) {
             NSManagedObject *object = [allObjects objectAtIndex:i];
             [object setValue:[NSNumber numberWithInt:i] forKey:@"order"];
         }
    
        // Reload data
        [arrayController rearrangeObjects];
        return YES;
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 2011-01-08
      • 1970-01-01
      • 2012-01-02
      • 1970-01-01
      • 2022-07-12
      • 2020-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多