Can't drag a custom data object.

  • Hi all,

    I'm trying to put a custom object into past board in order to perform a drag operation. It's working fine if I drag a string, but if I try to pass an object, I can't get it to work.

    - (BOOL)outlineView:(NSOutlineView*)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard {

    NSString* kOutlineViewGroupType = @"IFNode";

    [pboard clearContents];

    if([[items objectAtIndex:0] isParent]) {

      return NO;
    }

    itemsBeingDragged = items;

    [pboard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, kOutlineViewGroupType, nil]    owner:nil];

    ** This works.
    [pboard setString:[[items objectAtIndex:0] title] forType:NSStringPboardType];

    ** This doesn't (actually stops drag and drop working for my application until I logout).
    [pboard setData:[items objectAtIndex:0] forType:kOutlineViewGroupType];

    return YES;
    }

    Any help greatly appreciated.

    Cheers,

    Billy Flatman
    <b.flatman...>
  • On Apr 26, 2010, at 5:58 AM, Billy Flatman wrote:

    > I'm trying to put a custom object into past board in order to perform a drag operation.

    You can’t do that, for the same reason you can’t directly write a custom object to a file. The pasteboard basically stores bytes, so it has to be able to convert what you store in it to and from a stream of bytes. There are a limited number of data types it understands — strings, numbers, arrays, dictionaries and of course raw data.

    > ** This doesn't (actually stops drag and drop working for my application until I logout).
    > [pboard setData:[items objectAtIndex:0] forType:kOutlineViewGroupType];

    You’re passing the wrong type of object to the setData: parameter. Look at the header or the docs — it takes an NSData. You’re passing it some other custom object. The result is going to be an exception or a crash. (The reason this doesn’t produce a warning at compile time is because -objectAtIndex: just returns type id, which is compatible with anything (it’s like void* for objects.) You have to pay attention to what type of object you know is in the array.

    If you want to put a custom object in the pasteboard, there are several ways:

    (1) Wrap it in an NSValue via [NSValue valueWithPointer:]. This is kind of dangerous because you have to make sure the object won’t get dealloced before the pointer is eventually used, since -valueWithPointer: doesn’t retain the object.
    (2) Store some value that refers to the object, like a row number or an access key. You have to make sure that value will continue to work, i.e. the row number remains correct.
    (3) Implement a way to serialize the object into data or a dictionary/array. Implementing the NSCopying protocol is a standard way to do that.

    The first two techniques are OK for drag-n-drop because the lifetime of the pasteboard is limited. If you want to implement copy and paste you probably need to go with #3 because the pasteboard could stay around for an arbitrary amount of time.

    —Jens
  • Hi Jens,

    Thanks for your help. I've been trying to get the option 1 approach to work, but I don't know what I'm meant to do with my NSValue. I can't find how to convert it to an NSData type.

    Thanks again,

    Billy.

    On 26 Apr 2010, at 15:46, Jens Alfke wrote:

    >
    > On Apr 26, 2010, at 5:58 AM, Billy Flatman wrote:
    >
    >> I'm trying to put a custom object into past board in order to perform a drag operation.
    >
    > You can’t do that, for the same reason you can’t directly write a custom object to a file. The pasteboard basically stores bytes, so it has to be able to convert what you store in it to and from a stream of bytes. There are a limited number of data types it understands — strings, numbers, arrays, dictionaries and of course raw data.
    >
    >> ** This doesn't (actually stops drag and drop working for my application until I logout).
    >> [pboard setData:[items objectAtIndex:0] forType:kOutlineViewGroupType];
    >
    > You’re passing the wrong type of object to the setData: parameter. Look at the header or the docs — it takes an NSData. You’re passing it some other custom object. The result is going to be an exception or a crash. (The reason this doesn’t produce a warning at compile time is because -objectAtIndex: just returns type id, which is compatible with anything (it’s like void* for objects.) You have to pay attention to what type of object you know is in the array.
    >
    > If you want to put a custom object in the pasteboard, there are several ways:
    >
    > (1) Wrap it in an NSValue via [NSValue valueWithPointer:]. This is kind of dangerous because you have to make sure the object won’t get dealloced before the pointer is eventually used, since -valueWithPointer: doesn’t retain the object.
    > (2) Store some value that refers to the object, like a row number or an access key. You have to make sure that value will continue to work, i.e. the row number remains correct.
    > (3) Implement a way to serialize the object into data or a dictionary/array. Implementing the NSCopying protocol is a standard way to do that.
    >
    > The first two techniques are OK for drag-n-drop because the lifetime of the pasteboard is limited. If you want to implement copy and paste you probably need to go with #3 because the pasteboard could stay around for an arbitrary amount of time.
    >
    > —Jens

    Billy Flatman
    <b.flatman...>
  • On 27/04/2010, at 5:05 PM, Billy Flatman wrote:

    > Hi Jens,
    >
    > Thanks for your help. I've been trying to get the option 1 approach to work, but I don't know what I'm meant to do with my NSValue. I can't find how to convert it to an NSData type.

    NSData* data = [NSKeyedArchiver archivedDataWithRootObject:myValue];

    >> (3) Implement a way to serialize the object into data or a dictionary/array. Implementing the NSCopying protocol is a standard way to do that.

    I think perhaps Jens meant SCoding, not NSCopying. If you have an object that you want to be able to cut/paste or drag, adopt the NSCoding protocol and archive it directly (as above, but don't bother with a NSValue).

    --Graham
previous month april 2010 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today