18

迁移到 Swift4 后,以下代码引发编译错误:

public final class MediaItemView: NSView {

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

      // error: 'NSFilenamesPboardType' is unavailable in Swift:
      // use 'NSPasteboard.writeObjects(_:)' with file URLs
      let draggedTypes: [NSPasteboard.PasteboardType] = [NSFilenamesPboardType]
      registerForDraggedTypes(draggedTypes)
   }
}

NSFilenamesPboardTypeSwift4中的替代品是什么?如何file name在 Swift4 中注册拖动类型(在我的情况下为 mp3、wav、aiff、... 文件)?

谢谢!

4

7 回答 7

20

我已经解决了与此扩展的向后兼容性:

extension NSPasteboard.PasteboardType {

    static let backwardsCompatibleFileURL: NSPasteboard.PasteboardType = {

            if #available(OSX 10.13, *) {
                return NSPasteboard.PasteboardType.fileURL
            } else {
                return NSPasteboard.PasteboardType(kUTTypeFileURL as String)
            }

    } ()

}

这意味着您可以使用NSPasteboard.PasteboardType.backwardsCompatibleFileURL

于 2017-10-01T17:08:04.173 回答
12

我用这个作为解决方案

    //Temp solution for this
    let NSFilenamesPboardTypeTemp = NSPasteboard.PasteboardType("NSFilenamesPboardType")

    self.zipView.registerForDraggedTypes([NSFilenamesPboardTypeTemp])

这似乎是苹果的一个错误,他们将 api 标记为仅在 10.13 中工作。

我向苹果发射了一个错误:)

于 2017-09-16T13:11:25.463 回答
9

我喜欢这里为不推荐使用的变量提供的创造性解决方法NSFilenamesPboardType在研究了这个问题之后,使用等效的非弃用方法前进的一种方法是使用readObjects(forClasses:options:). 这也将使 WRT 能够在未来的 macOS 上运行更安全。它将像以下示例一样实现,使用 Swift 4.1 进行测试,基于在NSView情节提要中注册。

override func awakeFromNib()
{
    registerForDraggedTypes([.fileURL])
}

override func draggingEnded(_ sender: NSDraggingInfo)
{
    sender
        .draggingPasteboard()
        .readObjects(forClasses: [NSURL.self],
                     options: nil)?
        .forEach
        {
            // Do something with the file paths.
            if let url = $0 as? URL { print(url.path) }
        }
}

由于类数组参数 forreadObjects的类型[AnyClass]是使用 ofNSURL而不是 的原因URL

于 2018-07-15T00:00:03.893 回答
4

我也遇到了同样的问题,我的解决方案是NSPasteboard.PasteboardType使用kUTTypeURL. 我不确定这是否是最合适的方法(我想不是),但它至少适用于临时解决方法。

    let draggedType = NSPasteboard.PasteboardType(kUTTypeURL as String)
    self.tableView?.registerForDraggedTypes([draggedType])

此外,新的NSPasteboard.PasteboardTypehas.fileNameType(forPathExtension: "foo")方法。你应该试一试。但是不知何故,它在我的情况下不起作用。

于 2017-06-14T08:10:40.750 回答
1

结合使用Mark Bridges 的答案slboat 的答案,这是我想出的解决方案:

extension NSPasteboard.PasteboardType {

    /// The name of a file or directory
    static let fileName: NSPasteboard.PasteboardType = {
        return NSPasteboard.PasteboardType("NSFilenamesPboardType")
    }()
}

这在我的测试中按预期工作。

于 2018-11-03T21:19:23.270 回答
0

斯威夫特4,斯威夫特5

部分临时解决方法,但适用于 Swift4/5:

var chromeType: NSPasteboard.PasteboardType { return NSPasteboard.PasteboardType.init(rawValue: "org.chromium.drag-dummy-type") }
var finderNode: NSPasteboard.PasteboardType { return NSPasteboard.PasteboardType.init(rawValue: "com.apple.finder.node") }
var fileURLs: NSPasteboard.PasteboardType { return NSPasteboard.PasteboardType.init(rawValue: "NSFilenamesPboardType") }
var webarchive: NSPasteboard.PasteboardType { return NSPasteboard.PasteboardType.init(rawValue: "com.apple.webarchive") }

然后聚合为

var acceptableTypes: Set<NSPasteboard.PasteboardType> { return [.URL, .fileURL, .pdf, .png, .rtf, .rtfd, .tiff, finderNode, webarchive] }

然后在视图中使用确实加载方法:

//  Intercept drags
registerForDraggedTypes(Array(acceptableTypes))
于 2019-09-09T11:10:33.727 回答
0

斯威夫特 5

//MARK:- Managing a Dragging Session After an Image Is Released

    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
        let fetched = sender.draggingPasteboard.readObjects(forClasses:  [NSURL.self], options: nil)?
            .map({ (argv) -> String? in
                guard let url = argv as? URL else{
                    return nil
                }
                return url.path
            }).compactMap({$0})

        guard let result = fetched else{
            return false
        }
        // handle the result
        print(result)
        return true
    }
于 2020-03-14T14:48:59.327 回答