2012-10-22 3 views
0

객체 부모를 사용자 정의 순서로 지정할 수있는 간단한 테이블을 구현하려고합니다. parentTableView를 parentArrayController에 바인딩하고 sortDescriptor를 키 "order"로 설정하면 테이블에 부모 엔터티가 "order"키의 순서대로 표시되고 모든 것이 올바르게 작동합니다. 내가 끌어 충돌은 드래그 된 객체가 새 위치에 삽입하거나 추가 라인에서 발생하는 새로운 위치에 행을 삭제하려고하면 :CoreData 객체의 NSTableView에서 드래그 앤 드롭 재정렬이 작동하지 않습니다.

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

또는 [self.parentArrayController의 addObjects : draggedObjects ];

내가 뭘 잘못하고 있니? 여기

는 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 

답변

4

의 arrayController의 arrangedObjects 프록시 객체는 내가 검색해야한다고 컨텍스트의 관리 대상 객체

작업 코드는 다음과 같습니다.

#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 
+0

매우 유용한 코드입니다. 감사! – mharper