Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and Drop in Swift - Issues with Registering for Dragged Types?

Background

I am trying to do some simple Drag and Drop in Swift similar to the sample code from Apple for Cocoa Drag and Drop. I am not getting far before I have errors.

I have created a swift class dropView with code at bottom. self.registered for types seems like it worked as I get a long list of image types or the shorter list.

When I set the array for registering dragging types to TIF and jpeg types, I get no response for draggingEntered or draggingUpdated. It seems that I am missing something simple? I have the custom view set to the dropView class.

Separately, I get a host of errors when I drag a file (at least for TIF and jpeg) when the array is set to NSImage.imagePasteBoardTypes() see ** at bottom of post.

Questions

Why is draggingEntered or draggingUpdated not being called?

Other questions:

Am I registering for dragged types correctly? Is the array in the right format? Is the NSDraggingDestination property bit at the top of the file in the right spot?

Code

import Cocoa

class dropView: NSView, NSDraggingDestination {

init(frame: NSRect) {
    super.init(frame: frame)
    //let theArray = [NSImage.imagePasteboardTypes()]
    let theArray = ["NSTypedFilenamesPboardType:jpg",
        "NSTypedFilenamesPboardType:JPG",
        "NSTypedFilenamesPboardType:jpeg",
        "NSTypedFilenamesPboardType:JPEG",
        "NSTypedFilenamesPboardType:jpe",
        "NSTypedFilenamesPboardType:TIF"]

    registerForDraggedTypes(theArray)
    println("INIT and REGISTER")
    println(self.registeredDraggedTypes)
}

override func drawRect(dirtyRect: NSRect) {
    super.drawRect(dirtyRect)

    // Drawing code here.
}


override func draggingEntered(sender: NSDraggingInfo!) -> NSDragOperation {
    println("Dragging Entered")
    return NSDragOperation.Copy
}

override func draggingUpdated(sender: NSDraggingInfo!) -> NSDragOperation  {
    println("UPDATED")
    return NSDragOperation.Copy
}

}

** Errors when NSImage.imagePasteBoardTypes()

2014-06-21 11:34:38.728 DragAndDrop[96606:303] -[__NSArrayM length]: unrecognized selector sent to instance 0x610000049d80  
2014-06-21 11:34:38.729 DragAndDrop[96606:303] -[__NSArrayM length]: unrecognized selector sent to instance 0x610000049d80  
2014-06-21 11:34:38.730 DragAndDrop[96606:303] (
    0   CoreFoundation                      0x00007fff8ddaf25c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff83a5de75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8ddb212d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00007fff8dd0d322 ___forwarding___ + 1010
    4   CoreFoundation                      0x00007fff8dd0cea8 _CF_forwarding_prep_0 + 120
    5   LaunchServices                      0x00007fff8aee1b0a XCFStringHashCaseInsensitive + 111
    6   CoreFoundation                      0x00007fff8dc6afd8 CFBasicHashFindBucket + 1032
    7   CoreFoundation                      0x00007fff8dc989c9 CFSetGetValueIfPresent + 121
    8   CoreFoundation                      0x00007fff8dc9892c -[__NSCFSet member:] + 28
    9   CoreFoundation                      0x00007fff8dccb008 -[NSSet containsObject:] + 24
    10  CoreFoundation                      0x00007fff8dd18fcf -[NSSet intersectsSet:] + 735
    11  AppKit                              0x00007fff86c645ff -[NSView(NSDrag) _hitTest:dragTypes:] + 221
    12  AppKit                              0x00007fff86c645d2 -[NSView(NSDrag) _hitTest:dragTypes:] + 176
    13  AppKit                              0x00007fff86c645d2 -[NSView(NSDrag) _hitTest:dragTypes:] + 176
    14  AppKit                              0x00007fff86c6438c -[NSWindow(NSDrag) _findDragTargetFrom:] + 111
    15  AppKit                              0x00007fff86c63280 NSCoreDragTrackingProc + 476
    16  HIServices                          0x00007fff8b8a05a3 DoEnterLeaveHandler + 389
    17  HIServices                          0x00007fff8b8a2fdd CoreDragMessageHandler + 1741
    18  CoreFoundation                      0x00007fff8dd5ace8 __CFMessagePortPerform + 760
    19  CoreFoundation                      0x00007fff8dce08d9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    20  CoreFoundation                      0x00007fff8dce084e __CFRunLoopDoSource1 + 478
    21  CoreFoundation                      0x00007fff8dcd1886 __CFRunLoopRun + 1830
    22  CoreFoundation                      0x00007fff8dcd0f25 CFRunLoopRunSpecific + 309
    23  HIToolbox                           0x00007fff8b908a0d RunCurrentEventLoopInMode + 226
    24  HIToolbox                           0x00007fff8b9087b7 ReceiveNextEventCommon + 479
    25  HIToolbox                           0x00007fff8b9085bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
    26  AppKit                              0x00007fff8695726e _DPSNextEvent + 1434
    27  AppKit                              0x00007fff869568bb -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
    28  AppKit                              0x00007fff8694a9bc -[NSApplication run] + 553
    29  AppKit                              0x00007fff869357a3 NSApplicationMain + 940
    30  DragAndDrop                         0x00000001000033fd top_level_code + 109
    31  DragAndDrop                         0x000000010000343a main + 42
    32  libdyld.dylib                       0x00007fff8e1925fd start + 1
    33  ???                                 0x0000000000000003 0x0 + 3
)
2014-06-21 11:34:40.729 DragAndDrop[96606:303] -[__NSArrayM length]: unrecognized selector sent to instance 0x610000049d80
2014-06-21 11:34:40.730 DragAndDrop[96606:303] -[__NSArrayM length]: unrecognized selector sent to instance 0x610000049d80
2014-06-21 11:34:40.731 DragAndDrop[96606:303] (
    0   CoreFoundation                      0x00007fff8ddaf25c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff83a5de75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8ddb212d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00007fff8dd0d322 ___forwarding___ + 1010
    4   CoreFoundation                      0x00007fff8dd0cea8 _CF_forwarding_prep_0 + 120
    5   LaunchServices                      0x00007fff8aee1b0a XCFStringHashCaseInsensitive + 111
    6   CoreFoundation                      0x00007fff8dc6afd8 CFBasicHashFindBucket + 1032
    7   CoreFoundation                      0x00007fff8dc989c9 CFSetGetValueIfPresent + 121
    8   CoreFoundation                      0x00007fff8dc9892c -[__NSCFSet member:] + 28
    9   CoreFoundation                      0x00007fff8dccb008 -[NSSet containsObject:] + 24
    10  CoreFoundation                      0x00007fff8dd18fcf -[NSSet intersectsSet:] + 735
    11  AppKit                              0x00007fff86c645ff -[NSView(NSDrag) _hitTest:dragTypes:] + 221
    12  AppKit                              0x00007fff86c645d2 -[NSView(NSDrag) _hitTest:dragTypes:] + 176
    13  AppKit                              0x00007fff86c645d2 -[NSView(NSDrag) _hitTest:dragTypes:] + 176
    14  AppKit                              0x00007fff86c6438c -[NSWindow(NSDrag) _findDragTargetFrom:] + 111
    15  AppKit                              0x00007fff86c63280 NSCoreDragTrackingProc + 476
    16  HIServices                          0x00007fff8b89fca4 DoTrackingMessage + 370
    17  HIServices                          0x00007fff8b8a2b36 CoreDragMessageHandler + 550
    18  CoreFoundation                      0x00007fff8dd5ace8 __CFMessagePortPerform + 760
    19  CoreFoundation                      0x00007fff8dce08d9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    20  CoreFoundation                      0x00007fff8dce084e __CFRunLoopDoSource1 + 478
    21  CoreFoundation                      0x00007fff8dcd1886 __CFRunLoopRun + 1830
    22  CoreFoundation                      0x00007fff8dcd0f25 CFRunLoopRunSpecific + 309
    23  HIToolbox                           0x00007fff8b908a0d RunCurrentEventLoopInMode + 226
    24  HIToolbox                           0x00007fff8b9087b7 ReceiveNextEventCommon + 479
    25  HIToolbox                           0x00007fff8b9085bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
    26  AppKit                              0x00007fff8695726e _DPSNextEvent + 1434
    27  AppKit                              0x00007fff869568bb -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
    28  AppKit                              0x00007fff8694a9bc -[NSApplication run] + 553
    29  AppKit                              0x00007fff869357a3 NSApplicationMain + 940
    30  DragAndDrop                         0x00000001000033fd top_level_code + 109
    31  DragAndDrop                         0x000000010000343a main + 42
    32  libdyld.dylib                       0x00007fff8e1925fd start + 1
    33  ???                                 0x0000000000000003 0x0 + 3
)
like image 281
Chris Avatar asked Jun 21 '14 15:06

Chris


People also ask

Is it possible to do simple drag and drop in Swift?

I am trying to do some simple Drag and Drop in Swift similar to the sample code from Apple for Cocoa Drag and Drop. I am not getting far before I have errors. I have created a swift class dropView with code at bottom. self.registered for types seems like it worked as I get a long list of image types or the shorter list.

How do I make a view draggable in SwiftUI?

For the Drag, SwiftUI has a single method called onDrag (). By adding this modifier to a view, you are doing two important things: you are telling SwiftUI that the view is draggable, and you also set the data that will be attached to the drag operation (in the form of NSItemProvider objects).

What is nsitemprovider in SwiftUI drag and drop?

Drag and Drop with SwiftUI is very simple. However, if you are completely new to drag and drop on macOS/iOS, the challenge will be to understand NSItemProvider. This is the class that carries the information of the dragged data, and it is a class that has been around for many years.

What is the best example of drag and drop in Android?

For example, depending on your app needs, an image can be dragged as an Image, a URL, or raw data. Text can be dragged as simple text, rich text, etc. You may even need to drag your own custom type. Usually, most of the time implementing drag and drop, will be the time spent on that task, and not the UI part of the problem.


Video Answer


2 Answers

(Swift 3, Xcode 8b6, OSX 10.11)

Apple recommends that the older style of pasteboard types should no longer be used and to use UTIs where possible - the better version is

self.register(forDraggedTypes: [kUTTypeURL as String])

This means that you receive drags from the Finder, for all filetypes.

Since NSImage.imagePasteboardTypes has been deprecated without replacement, you should handle the filtering in draggingEntered:

override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
        let pasteboard = sender.draggingPasteboard()
        let filteringOptions = [NSPasteboardURLReadingContentsConformToTypesKey:NSImage.imageTypes()]
                if pasteboard.canReadObject(forClasses: [NSURL.self], options: filteringOptions) {
                        return NSDragOperation.copy
        }      
        return NSDragOperation() //alternatively: []
}

(credit for the use of NSPasteboardURLReadingContentsConformToTypesKey goes to @TroutDev's tutorial here)

like image 115
green_knight Avatar answered Oct 27 '22 03:10

green_knight


Regarding the crash

Separately, I get a host of errors when I drag a file (at least for TIF and jpeg) when the array is set to NSImage.imagePasteBoardTypes() see ** at bottom of post.

NSImage.imagePasteboardTypes() already returns an array, so using it like this:

let theArray = NSImage.imagePasteboardTypes()

instead of like this

let theArray = [NSImage.imagePasteboardTypes()]

will fix the crash.

Regarding NSDragDestination

Why is draggingEntered or draggingUpdated not being called?

If you're dragging from Finder, you probably want let types = [NSFilenamesPboardType]. The code you have means you have to place data onto the pasteboard yourself -- Finder doesn't put file contents onto the pasteboard, it puts filenames.

Is the NSDraggingDestination property bit at the top of the file in the right spot?

Yep! : NSDraggingDestination tells Swift that you're about to implement the protocol.

Working example

// Public domain
import Cocoa

class DragView: NSView, NSDraggingDestination {
    init(frame: NSRect) {
        super.init(frame: frame)
        let types = [NSFilenamesPboardType]
        registerForDraggedTypes(types)
        println(self.registeredDraggedTypes)
    }

    override func drawRect(dirtyRect: NSRect)  {
        super.drawRect(dirtyRect)
        NSColor.whiteColor().set()
        NSRectFill(dirtyRect)
    }

    override func draggingEntered(sender: NSDraggingInfo!) -> NSDragOperation  {
        println("hello")
        return NSDragOperation.Copy
    }
}
like image 29
hao Avatar answered Oct 27 '22 04:10

hao