2010-12-12 33 views
2

Je dois faire glisser une référence vers un NSManagedObject entre deux vues de table de mon application. Quel est le type de NSPasteboard préféré pour stocker une référence à un objet NSManagedObject?Type NSPasteboard pour NSManagedObject

Ma solution actuelle consiste à stocker l'URIRepresentation de NSManagedObjectID de l'objet dans un NSPasteboardTypeString. Je soupçonne qu'il existe une solution plus élégante.

Répondre

3

Il n'existe pas de type standard pour tous les objets de modèle, car les objets de votre modèle et la manière dont ils sont gérés sont propres à votre application. S'il y avait un type de carton pour tous, il n'y aurait pas de distinction entre eux. Votre propre objet personnalisé devrait avoir son propre type de glisser. Utilisez simplement une chaîne qui a du sens (peut-être un #define donc vous pouvez le trouver avec auto-complete dans Xcode) comme "MyObjectPboardType" qui se résout à "com.yourcompany.yourapp.yourobjecttype". Utilisez -declareTypes de NSPasteboard: owner: pour déclarer votre nouveau type, puis utilisez -setString: forType: ou l'une des autres méthodes -set?: ForType: pour définir les informations pour le type de votre objet.

Dans votre cas, l'utilisation de l'identifiant d'objet est un identifiant parfaitement acceptable. Souvenez-vous simplement que les ID d'objet des objets gérés changent lorsqu'ils sont nouveaux ou persistants.

1

Si vous glissez dans des tables dans la même application, vous pouvez aussi mettre dans le pasteboard les rowIndexes (indexPaths dans le cas où vous glissez depuis un outlineView) des objets dans tableView (outlineView). Cela pourrait aussi vous épargner un accès CoreData non nécessaire si la source de données de tableViews est NSArrayController (NSTreeController pour outlineView). Vous pouvez ensuite récupérer facilement les objets glissés lors de l'acceptation de la suppression depuis l'objet 'info' transmis aux deux méthodes tableView: validateDrop: proposedRow: proposedDropOperation: 'et' tableView: acceptDrop: row: dropOperation: 'auront une référence à la tableView d'origine le glisser sous le chemin de la clé 'draggingSource'.

Voici une implémentation simple:

extern NSString *const kMyLocalDragType = @"com.whatever.localDragType"; 
@implementation MyArrayControllerDataSource 
    . 
    . 
    . 
#pragma mark - NSTableViewDataSource (Drag & Drop) 
+ (NSArray *)dragTypes { 
    // convenience method returning all class's supported dragTypes 
    return @[kMyLocalDragType]; 
} 
- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard { 
    [pboard declareTypes:[[self class] dragTypes] owner:self]; 
    for (NSString *aDragType in [[self class] dragTypes]) { 
     if (aDragType == kMyLocalDragType) { 
     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; // we are supporting drag&drop of multiple items selected  
     [pboard setData:data forType:aDragType]; 
     } 
     . 
     . // logic for other dragTypes 
     . 
    } 
    return YES; 
} 
- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id<NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation { 
    NSArray *dragTypes = [info draggingPasteboard] types]; 
    for (id aDragType in dragTypes) { 
     if (aDragType == kMyLocalDragType) { 
     return NSDragOperationCopy; 
     } 
    } 
    . 
    .// Other logic for accepting drops/affect drop operation 
    . 
} 

- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation { 
    if ([info draggingPasteboard] types] containsObject:kMyLocalDragType]) { 
     // Retrieve the index set from the pasteboard: 
     NSData *data = [[info draggingPasteboard] dataForType:kMyLocalDragType]; 
     NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
     NSArray *droppedObjects = [self retrieveFromTableView:tableView objectsAtRows:rowIndexes]; 
     // droppedObjects contains dragged and dropped objects, do what you 
     // need to do with them, then add them to this dataSource: 
     [self.content insertObjects:droppedObjects]; 
     [tableView reloadData]; 
     [tableView deselectAll:nil]; 
     return YES; 
    } 
     . 
     . // other logic for accepting drops of other dragTypes supported. 
     . 
} 

#pragma mark - Helpers 
- (NSArray <NSManagedObject *> *)retrieveFromTableView:(NSTableView *)tableView objectsAtRowIndexes:(NSIndexSet *)rowIndexes { 
    id dataSource = [tableView dataSource]; 
    if ([dataSource respondsToSelector:@selector(content)]) { 
     if ([dataSource.content respondsToSelector:@selector(objectsAtIndexes:)]) { 
      return [datasource content] objectsAtIndexes:rowIndexes]; 
     } 
    } 
    return @[]; //We return an empty array in case introspection check failed 
}