Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中实现拖放区域_Swift_Macos_Cocoa - Fatal编程技术网

在Swift中实现拖放区域

在Swift中实现拖放区域,swift,macos,cocoa,Swift,Macos,Cocoa,我最近开始使用Swift构建OSX应用程序,我想知道如何实现拖放区 更具体地说,我构建了一个处理图像的应用程序,但目前,用户必须手动输入输入图像的路径或使用文件选择器(这很烦人)。我想改进我的应用程序,允许用户通过简单的拖放输入图像(我只需要检索表示图像路径的字符串) 我如何才能做到这一点?下面是我在应用程序中使用的一个示例 如有必要,将对NSDraggingDestination的一致性添加到子类声明中(对于NSImageView不需要,因为它已经符合协议) 声明接受类型的数组(至少NSFil

我最近开始使用Swift构建OSX应用程序,我想知道如何实现拖放区

更具体地说,我构建了一个处理图像的应用程序,但目前,用户必须手动输入输入图像的路径或使用文件选择器(这很烦人)。我想改进我的应用程序,允许用户通过简单的拖放输入图像(我只需要检索表示图像路径的字符串)


我如何才能做到这一点?

下面是我在应用程序中使用的一个示例

  • 如有必要,将对
    NSDraggingDestination
    的一致性添加到子类声明中(对于
    NSImageView
    不需要,因为它已经符合协议)
  • 声明接受类型的数组(至少
    NSFilenamesPboardType
  • 将这些类型注册到
    RegisterForDragedTypes
  • 覆盖
    draggingEntered
    draggingUpdated
    performdraggoperation
  • 从这些方法返回一个
    nsdragooperation
  • draggingPasteboard
    数组中获取文件路径
  • 在我的示例中,我添加了一个函数来检查文件扩展名是否在我们想要的扩展名中

    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
        }
    }
    

    Swift 4

    class MyImageView: NSImageView {
    
        let NSFilenamesPboardType = NSPasteboard.PasteboardType("NSFilenamesPboardType")
    
        override func draw(_ dirtyRect: NSRect) {
            super.draw(dirtyRect)
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            // Declare and register an array of accepted types
            registerForDraggedTypes([NSPasteboard.PasteboardType(kUTTypeFileURL as String),
                                     NSPasteboard.PasteboardType(kUTTypeItem as String)])
        }
    
        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
        }
    }
    

    此实现允许多个文件

    只需在Interface Builder中将view类设置为
    DragView
    ,在控制器中实现
    DragViewDeleteGate
    ,然后在Interface Builder中连接代理出口。这样,您将获得一个带有文件URL的委托回调

    func-dragViewDidReceive(文件URL:[URL])
    {
    //耶!
    }
    
    DragView.swift

    //
    //斯威夫特
    //
    //版权所有(c)2020 Geri Borbáshttp://www.twitter.com/_eppz
    //
    //特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人在不受限制的情况下经营本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向其提供软件的人员在符合以下条件的情况下这样做:
    //上述版权声明和本许可声明应包含在软件的所有副本或实质部分中。
    //本软件按“原样”提供,无任何明示或暗示的担保,包括但不限于适销性、特定用途适用性和非侵权性担保。在任何情况下,作者或版权持有人均不对任何索赔、损害赔偿或其他责任负责,无论是合同诉讼、侵权诉讼还是其他诉讼,均由本软件或本软件的使用或其他交易引起,或与本软件或本软件的使用或其他交易有关。
    进口可可
    @objc协议DragViewDelegate
    {
    func-dragViewDidReceive(文件URL:[URL])
    }
    类DragView:NSView
    {
    @IBV弱var委托:DragViewDelegate?
    让fileExtensions=[“pdf”]
    必需初始化?(编码器:NSCoder)
    {
    super.init(编码器:编码器)
    颜色(至:。清除)
    registerForDraggedTypes([.fileURL])
    }
    覆盖函数draggingEntered(uggininfo:NSDraggingInfo)->nsdragooperation
    {
    var containsMatchingFiles=false
    DragginInfo.draggingPasteboard.readObjects(对于类:[NSURL.self],选项:nil)?.forEach
    {
    每个项目
    如果让eachURL=eachObject作为?URL
    {
    containsMachingfiles=containsMachingfiles | | fileExtensions.contains(eachURL.pathExtension.lowercased())
    如果包含smatchingfiles{print(eachURL.path)}
    }
    }
    交换机(包含通讯文件)
    {
    大小写正确:
    颜色(至:。secondaryLabelColor)
    返回,收到
    案例错误:
    颜色(至:。disabledControlTextColor)
    return.init()
    }
    }
    重写func performDragOperation(ugginInfo:nsDragginInfo)->Bool
    {
    //收集URL。
    var matchingfileurl:[URL]=[]
    DragginInfo.draggingPasteboard.readObjects(对于类:[NSURL.self],选项:nil)?.forEach
    {
    每个项目
    如果
    让eachURL=eachObject作为?URL,
    fileExtensions.contains(eachURL.pathExtension.lowercased())
    {matchingfileurl.append(eachURL)}
    }
    //如果有的话,
    guard matchingFileURLs.count>0
    else{return false}
    //传给代表。
    委托?.dragViewDidReceive(文件URL:匹配文件URL)
    返回真值
    }
    覆盖功能拖动退出(u发送方:NSDraggingInfo?)
    {颜色(到:。清除)}
    覆盖函数拖动(发送方:NSDraggingInfo)
    {颜色(到:。清除)}
    }
    扩展DragView
    {
    func颜色(到颜色:NSColor)
    {
    self.wantsLayer=true
    self.layer?.backgroundColor=color.cgColor
    }
    }
    
    谢谢Eric D。Apple doc在这里:警告:NSURLPboardType在Swift 4中不再工作了,还有一个问题。如果您知道如何在Swift 4中使用NSURLPboardType和这些其他常量,请进行编辑或添加您自己的答案。谢谢。谢谢你的Swift 4版本。Xcode要求我在imagePath和path之前添加“let”,以使代码正常工作。