Implementing a drag-and-drop zone in Swift

前端 未结 3 1302
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-12 23:14

I recently started using Swift to build OS X apps and I am wondering how I could implement a drag-and-drop zone.

More specifically, I built an app that processes ima

3条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-12 23:40

    Here's an example I'm using in an application.

    1. Add conformance to NSDraggingDestination to your subclass declaration if necessary (not needed for NSImageView because it already conforms to the protocol)
    2. Declare an array of accepted types (at least NSFilenamesPboardType)
    3. Register these types with registerForDraggedTypes
    4. Override draggingEntered, draggingUpdated and performDragOperation
    5. Return an NSDragOperation from these methods
    6. Get the file(s) path(s) from the draggingPasteboard array

    In my example I've added a function to check if the file extension is amongst the ones we want.

    Swift 2

    class MyImageView: NSImageView {
    
        override func drawRect(dirtyRect: NSRect) {
            super.drawRect(dirtyRect)
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            // Declare and register an array of accepted types
            registerForDraggedTypes([NSFilenamesPboardType, NSURLPboardType, NSPasteboardTypeTIFF])
        }
    
        let fileTypes = ["jpg", "jpeg", "bmp", "png", "gif"]
        var fileTypeIsOk = false
        var droppedFilePath: String?
    
        override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
            if checkExtension(sender) {
               fileTypeIsOk = true
               return .Copy
            } else {
               fileTypeIsOk = false
               return .None
            }
        }
    
        override func draggingUpdated(sender: NSDraggingInfo) -> NSDragOperation {
            if fileTypeIsOk {
                return .Copy
            } else {
                return .None
            }
        }
    
        override func performDragOperation(sender: NSDraggingInfo) -> Bool {
            if let board = sender.draggingPasteboard().propertyListForType("NSFilenamesPboardType") as? NSArray,
                imagePath = board[0] as? String {
                // THIS IS WERE YOU GET THE PATH FOR THE DROPPED FILE
                droppedFilePath = imagePath
                return true
            }
            return false
        }
    
        func checkExtension(drag: NSDraggingInfo) -> Bool {
            if let board = drag.draggingPasteboard().propertyListForType("NSFilenamesPboardType") as? NSArray,
                path = board[0] as? String {
                let url = NSURL(fileURLWithPath: path)
                if let fileExtension = url.pathExtension?.lowercaseString {
                    return fileTypes.contains(fileExtension)
                }
            }
            return false
        }
    }
    

    Swift 3

    class MyImageView: NSImageView {
    
        override func draw(_ dirtyRect: NSRect) {
            super.draw(dirtyRect)
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            // Declare and register an array of accepted types
            register(forDraggedTypes: [NSFilenamesPboardType, NSURLPboardType, NSPasteboardTypeTIFF])
        }
    
        let fileTypes = ["jpg", "jpeg", "bmp", "png", "gif"]
        var fileTypeIsOk = false
        var droppedFilePath: String?
    
        override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
            if checkExtension(drag: sender) {
                fileTypeIsOk = true
                return .copy
            } else {
                fileTypeIsOk = false
                return []
            }
        }
    
        override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation {
            if fileTypeIsOk {
                return .copy
            } else {
                return []
            }
        }
    
        override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
            if let board = sender.draggingPasteboard().propertyList(forType: "NSFilenamesPboardType") as? NSArray,
                imagePath = board[0] as? String {
                // THIS IS WERE YOU GET THE PATH FOR THE DROPPED FILE
                droppedFilePath = imagePath
                return true
            }
            return false
        }
    
        func checkExtension(drag: NSDraggingInfo) -> Bool {
            if let board = drag.draggingPasteboard().propertyList(forType: "NSFilenamesPboardType") as? NSArray,
                path = board[0] as? String {
                let url = NSURL(fileURLWithPath: path)
                if let fileExtension = url.pathExtension?.lowercased() {
                    return fileTypes.contains(fileExtension)
                }
            }
            return false
        }
    }
    

提交回复
热议问题