I've subclassed NSCollectionView and I'm trying to receive dragged files from the Finder. I'm receiving draggingEntered:
and returning an appropriate value, but I'm never receiving prepareForDragOperation:
(nor any of the methods after that in the process). Is there something obvious I'm missing here?
Code:
- (void)awakeFromNib
{
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
NSLog(@"entered"); //Happens
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType])
{
NSLog(@"copy"); //Happens
return NSDragOperationCopy;
}
return NSDragOperationNone;
}
- (BOOL)prepareForDragOperation:(id <NSDr开发者_StackOverflowaggingInfo>)sender
{
NSLog(@"prepare"); //Never happens
return YES;
}
This is pretty late, but I found the problem:
NSCollectionView silently provides an incompatible implementation of:
-(NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
...and Apple hasn't documented this. If you simply implement that method to re-invoke the draggingEntered method, everything works fine, e.g.:
-(NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
return [self draggingEntered:sender];
}
(I came to SO hoping to find an explanation of what "magic" this custom implementation provides, since that too is ... undocumented (thanks, Apple!). I'm guessing it does something clever with managing an insertion-point within the CollectionView?).
UPDATE: it seems the special magic is inside the NSCollectionView's delegate object. For some reason, Xcode4 was claiming there was no delegate for me, but assigning it built and ran OK. Check out all the custom / semi-documented drag/drop methods there.
(or just do as I describe above and override the custom behaviour, and implement something that works and you can understand)
You might want to try these delegate methods from the NSCollectionViewDelegate Protocol
- (NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id <NSDraggingInfo> )draggingInfo proposedIndex:(NSInteger *)proposedDropIndex dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation;
- (BOOL)collectionView:(NSCollectionView *)collectionView acceptDrop:(id <NSDraggingInfo> )draggingInfo index:(NSInteger)index dropOperation:(NSCollectionViewDropOperation)dropOperation;
- (BOOL)collectionView:(NSCollectionView *)collectionView canDragItemsAtIndexes:(NSIndexSet *)indexes withEvent:(NSEvent *)event;
- (NSImage *)collectionView:(NSCollectionView *)collectionView draggingImageForItemsAtIndexes:(NSIndexSet *)indexes withEvent:(NSEvent *)event offset:(NSPointPointer)dragImageOffset;
- (NSArray *)collectionView:(NSCollectionView *)collectionView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropURL forDraggedItemsAtIndexes:(NSIndexSet *)indexes;
- (BOOL)collectionView:(NSCollectionView *)collectionView writeItemsAtIndexes:(NSIndexSet *)indexes toPasteboard:(NSPasteboard *)pasteboard;
The first two methods in particular.
I went through this a while ago. It seemed counterintuitive to me, but the only way I could get it to work was to set up the associated scroll view as the drop target.
精彩评论