美文网首页MacOS 开发收录
MacOS 开发(十六) : 文件拖拽

MacOS 开发(十六) : 文件拖拽

作者: SoaringHeart | 来源:发表于2021-04-17 16:47 被阅读0次

    文件拖拽的核心是拖拽目标视图 (DragDestinationView),此方法会检测目标是否可拖拽类型,拖拽文件信息,图像会返回 image,颜色返回 Color,docx,ppt,zip 等返回路径(URL)。

    import Cocoa
    import CocoaExpand
    
    @objc protocol DragDestinationViewDelegate: NSObjectProtocol {
        @objc optional func processImage(_ image: NSImage, pasteBoard: NSPasteboard)
        
        @objc optional func process(_ obj: Any, pasteBoard: NSPasteboard)
    }
    
    ///拖拽目标视图
    @available(macOS 10.13, *)
    class DragDestinationView: NSView {
        
        var delegate: DragDestinationViewDelegate?
        ///支持拖入的类型
        var supportedTypes: [NSPasteboard.PasteboardType] = [.tiff, .color, .string, .fileURL, .html]{
            willSet{
                self.registerForDraggedTypes(newValue)
            }
        }
        ///支持拖入的子类型
        var acceptableUTITypes: [NSPasteboard.ReadingOptionKey : Any] {
            let types = [NSImage.imageTypes,
                         NSString.readableTypeIdentifiersForItemProvider,
                         NSURL.readableTypeIdentifiersForItemProvider].flatMap { $0 }
            return [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes : types]
        }
        
        var isReceivingDrag = false {
            didSet {
                needsDisplay = true
            }
        }
        
        // MARK: -lifecycle
        convenience init(types: [NSPasteboard.PasteboardType]) {
            self.init()
            self.registerForDraggedTypes(types)
        }
            
        // MARK: -drag
        override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
            return .copy
        }
        
        override func draggingExited(_ sender: NSDraggingInfo?) {
            isReceivingDrag = false
        }
        
        override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {
            return true
        }
    //    //仅支持 image 可用此方法   
    //    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
    //
    //        isReceivingDrag = false
    //        let pasteBoard = sender.draggingPasteboard
    //        guard let image = NSImage(pasteboard: pasteBoard) else {
    //            return false
    //        }
    //        delegate?.processImage?(image, pasteBoard: pasteBoard)
    //        return true
    //    }
        
        override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
            isReceivingDrag = false
            let pasteBoard = sender.draggingPasteboard
            
            let classArray: [AnyClass] = [NSImage.self, NSColor.self, NSString.self, NSURL.self]
            return pasteBoard.readObjects(forClasses: classArray, options: acceptableUTITypes) { (obj) in
                if let value = obj as? NSImage {
                    self.delegate?.processImage?(value, pasteBoard: pasteBoard)
                } else {
                    self.delegate?.process?(obj, pasteBoard: pasteBoard)
                }
            }
        }
        
        override func concludeDragOperation(_ sender: NSDraggingInfo?) {
    
        }
    }
    
    public extension NSPasteboard{
        ///获取拖拽元素的信息
        @available(OSX 10.13, *)
        var propertyList: [Any]? {
            if let board = self.propertyList(forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? [String] {
                print("FILE: \(board)")
                return board
            }
            
            if let board = self.propertyList(forType: .URL) as? [URL] {
                print("URL: \(board)")
                return board
            }
            
            if let board = self.propertyList(forType: .string) as? [String] {
                print("STRING: \(board)")
                return board
            }
            
            if let board = self.propertyList(forType: .html) as? [String] {
                print("HTML: \(board)")
                return board
            }
            return nil
        }
        
        ///拖拽的本地文件路径
        @available(OSX 10.13, *)
        var draggedFileURL: NSURL? {
            if let property = propertyList?.first as? String {
                print(property)
                return NSURL(fileURLWithPath: property)
            }
            return nil
        }
        ///解析拖拽到目标视图上的信息同时options 参数限制可拖入子元素的类型( nil 表示不限类型)
        func readObjects(forClasses classArray: [AnyClass] = [NSImage.self, NSColor.self, NSString.self, NSURL.self],
                         options: [NSPasteboard.ReadingOptionKey : Any]? = nil,
                         handler: ((Any)->Void)? = nil) -> Bool {
            guard let pasteboardObjects = readObjects(forClasses: classArray, options: options),
                  pasteboardObjects.count > 0 else {
                return false
            }
            
            pasteboardObjects.forEach { (obj) in
                switch obj {
                case let value as NSImage:
                    print(#function, #line, "NSImage", value)
                    handler?(value)
                    
                case let value as NSString:
                    print(#function, #line, "NSString", value)
                    handler?(value)
    
                case let value as NSColor:
                    print(#function, #line, "NSColor", value)
                    handler?(value)
    
                case let value as URL:
                    print(#function, #line, "URL", value.absoluteString.removingPercentEncoding ?? "")
                    if let image = NSImage(contentsOfFile: value.path) {
                        print(#function, #line, image)
                        handler?(image)
                    } else {
                        handler?(value)
                    }
                    
                default:
                    print(#function, #line, obj)
                    handler?(obj)
                    break
                }
            }
            return true
        }
    }
    
    

    github

    相关文章

      网友评论

        本文标题:MacOS 开发(十六) : 文件拖拽

        本文链接:https://www.haomeiwen.com/subject/yitplltx.html