自定义NSView拖放图像

时间:2015-05-07 09:12:44

标签: image cocoa drag-and-drop nsview

我正在开发OS X应用程序,我似乎无法让拖放工作。我用Google搜索了很多,但是关于这个主题的大多数帖子都至少有几年的历史,而且没有一个帖子告诉我在思想中缺少的链接。

无论如何,这是我正在努力做的事情。我的桌面上有一个图像,我希望能够将其拖放到我的自定义NSView中。自定义视图是名为CircularImageView的自定义NSView的子对象,并且是图层备份的,并且仅在屏幕上显示圆形图像。

以下是代码:

import Cocoa
import MCTools

@objc public protocol DragAndDropCircularImageViewDelegate {
    func imageDumped(sender: AnyObject!)
}

@IBDesignable @objc public class DragAndDropCircularImageView: CircularImageView {
    // This class provides the Drag And Drop Feature to the CircularImageView Class.

    // MARK: New in this class

    var highlight: Bool = false
    public var delegate: DragAndDropCircularImageViewDelegate?

    private func registerForDraggedImages() {
        self.registerForDraggedTypes(NSImage.imageTypes())
    }

    // MARK: CircularImageView Stuff

    public override var image: NSImage? {
        didSet {
            if let newImage = image {
                delegate?.imageDumped(self)
            }
        }
    }

    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.registerForDraggedImages()
    }

    public override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.registerForDraggedImages()
    }

    public override func updateLayer() {
        super.updateLayer()

        if highlight == true {

        }
    }

    // MARK: NS Dragging Destination Protocol

    public override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
        // When a drag enters our drop zone.
        if NSImage.canInitWithPasteboard(sender.draggingPasteboard()) {
            if ((sender.draggingSourceOperationMask().rawValue & NSDragOperation.Copy.rawValue) > 0) {
                highlight = true
                self.needsLayout = true

                sender.enumerateDraggingItemsWithOptions(.Concurrent, forView: self, classes: [NSPasteboardItem.self], searchOptions: [NSPasteboardURLReadingContentsConformToTypesKey: self], usingBlock: { (draggingItem, idx, stop) -> Void in

                    return
                })
            }
            return NSDragOperation.Copy
        }
        return NSDragOperation.None
    }

    public override func draggingExited(sender: NSDraggingInfo?) {
        // When drag exits our drop zone remove highlight of the drop zone.
        println("\(self)draggingExited")
        highlight = false
        self.needsLayout = true
    }

    public override func prepareForDragOperation(sender: NSDraggingInfo) -> Bool {
        // Update view for hovering drop.
        println("\(self)prepareForDragOperation")
        highlight = false
        self.needsLayout = true
        // Can we accept the drop?
        return NSImage.canInitWithPasteboard(sender.draggingPasteboard())
    }

    public override func performDragOperation(sender: NSDraggingInfo) -> Bool {
        // Handle the drop data.
        println("\(self)performDragOperation \(sender)")
        if NSImage.canInitWithPasteboard(sender.draggingPasteboard()) {
            self.image = NSImage(pasteboard: sender.draggingPasteboard())
        }
        return true
    }

    // MARK: Interface Builder Stuff
}

我看过一些我应该使用的帖子:

self.registerForDraggedTypes([NSFilenamesPboardType])

而不是:

self.registerForDraggedTypes(NSImage.imageTypes())

但是这似乎不适用于我的情况,当我使用NSFileNamesPboardType时,即使在调用任何NSDraggingDestination协议消息之前,我也会收到以下调试消息:

2015-05-07 11:07:19.583 CircularImageViewTest[44809:14389647] -[CircularView.DragAndDropCircularImageView copyWithZone:]: unrecognized selector sent to instance 0x608000166d80
(lldb) p 0x608000166d80
(Int) $R0 = 106102873550208

我不明白这是如何运作的。在某个地方框架尝试copyWithZone一个整数?任何人都可以向我解释这个吗?

任何帮助将不胜感激。提前谢谢。

1 个答案:

答案 0 :(得分:0)

好的,下面的代码可行。这一切都是由draggingEntered中的sender.enumerateDraggingItemsWithOptions引起的。 Apple框架调用时出现问题。

import Cocoa
import MCTools

@objc public protocol DragAndDropCircularImageViewDelegate {
    func imageDumped(sender: AnyObject!)
}

@IBDesignable @objc public class DragAndDropCircularImageView: CircularImageView {
    // This class provides the Drag And Drop Feature to the CircularImageView Class.

    // MARK: New in this class

    var highlight: Bool = false
    public weak var delegate: DragAndDropCircularImageViewDelegate?

    private func registerForDraggedImages() {
//        self.registerForDraggedTypes(NSImage.imageTypes())
        self.registerForDraggedTypes([NSFilenamesPboardType])
    }

    // MARK: CircularImageView Stuff

    public override var image: NSImage? {
        didSet {
            if let newImage = image {
                delegate?.imageDumped(self)
            }
        }
    }

    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.registerForDraggedImages()
    }

    public override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.registerForDraggedImages()
    }

    public override func updateLayer() {
        super.updateLayer()

        if highlight == true {

        }
    }

    // MARK: NS Dragging Destination Protocol

    public override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
        // When a drag enters our drop zone.
        if NSImage.canInitWithPasteboard(sender.draggingPasteboard()) {
            if ((sender.draggingSourceOperationMask().rawValue & NSDragOperation.Copy.rawValue) > 0) {
                highlight = true
                self.needsLayout = true
            }
            return NSDragOperation.Copy
        }
        return NSDragOperation.None
    }

    public override func draggingExited(sender: NSDraggingInfo?) {
        // When drag exits our drop zone remove highlight of the drop zone.
        println("\(self)draggingExited")
        highlight = false
        self.needsLayout = true
    }

    public override func prepareForDragOperation(sender: NSDraggingInfo) -> Bool {
        // Update view for hovering drop.
        println("\(self)prepareForDragOperation")
        highlight = false
        self.needsLayout = true
        // Can we accept the drop?
        return NSImage.canInitWithPasteboard(sender.draggingPasteboard())
    }

    public override func performDragOperation(sender: NSDraggingInfo) -> Bool {
        // Handle the drop data.
        println("\(self)performDragOperation \(sender)")
        if NSImage.canInitWithPasteboard(sender.draggingPasteboard()) {
            self.image = NSImage(pasteboard: sender.draggingPasteboard())
            self.delegate!.imageDumped(self)
        }
        return true
    }

    // MARK: Interface Builder Stuff
}