Swift 中的拖放 - 注册拖动类型的问题?
Posted
技术标签:
【中文标题】Swift 中的拖放 - 注册拖动类型的问题?【英文标题】:Drag and Drop in Swift - Issues with Registering for Dragged Types? 【发布时间】:2014-08-12 03:40:09 【问题描述】:背景
我正在尝试在 Swift 中进行一些简单的拖放操作,类似于 Apple 为 Cocoa Drag and Drop 提供的示例代码。在出现错误之前,我并没有走多远。
我创建了一个 swift 类 dropView,底部有代码。 self.registered for types 似乎很有效,因为我得到了一长串图像类型或更短的列表。
当我将用于注册拖动类型的数组设置为 TIF 和 jpeg 类型时,我没有收到 draggingEntered 或 draggingUpdated 的响应。看来我错过了一些简单的东西?我将自定义视图设置为 dropView 类。
另外,当数组设置为 NSImage.imagePasteBoardTypes() 时,当我拖动文件(至少对于 TIF 和 jpeg)时,我会遇到很多错误,请参阅帖子底部的 **。
问题
为什么没有调用 draggingEntered 或 draggingUpdated?
其他问题:
我是否正确注册了拖动类型? 数组的格式是否正确? 文件顶部的 NSDraggingDestination 属性位是否在正确位置?
代码
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
** 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
)
【问题讨论】:
【参考方案1】:(Swift 3、Xcode 8b6、OSX 10.11)
Apple recommends 表示不应再使用旧样式的粘贴板类型,并尽可能使用UTIs - 更好的版本是
self.register(forDraggedTypes: [kUTTypeURL as String])
这意味着您会收到来自 Finder 的拖拽,适用于所有文件类型。
由于NSImage.imagePasteboardTypes
已被弃用且没有替换,您应该在 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: []
(使用 NSPasteboardURLReadingContentsConformToTypesKey 归功于 @TroutDev 的 tutorial here)
【讨论】:
在 Xcode 9 中是registerForDraggedTypes([.URL])
。另外,NSPasteboardURLReadingContentsConformToTypesKey
不见了,不知道替换的是什么。【参考方案2】:
关于崩溃
另外,当数组设置为 NSImage.imagePasteBoardTypes() 时,当我拖动文件(至少对于 TIF 和 jpeg)时,我会遇到很多错误,请参阅帖子底部的 **。
NSImage.imagePasteboardTypes()
已经返回一个数组,所以像这样使用它:
let theArray = NSImage.imagePasteboardTypes()
而不是这样
let theArray = [NSImage.imagePasteboardTypes()]
将修复崩溃。
关于 NSDragDestination
为什么没有调用 draggingEntered 或 draggingUpdated?
如果您从 Finder 中拖动,您可能需要let types = [NSFilenamesPboardType]
。您拥有的代码意味着您必须自己将数据放置到粘贴板上——Finder 不会将文件内容放置到粘贴板上,而是放置文件名。
文件顶部的 NSDraggingDestination 属性位是否在正确位置?
是的! : NSDraggingDestination
告诉 Swift 你即将实现协议。
工作示例
// 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
【讨论】:
感谢您的详细解答。当我从这个例子开始时,Cocoa Drag and Drop,所以如果我阅读 NSPasteboard 类文档,objective-C 代码适用于 [self registerForDraggedTypes:[NSImage imagePasteboardTypes]];已在 10.10 中弃用?以上是关于Swift 中的拖放 - 注册拖动类型的问题?的主要内容,如果未能解决你的问题,请参考以下文章