Подтвердить что ты не робот

Swift 4: NSFilenamesPboardType недоступен. Что использовать для registerForDraggedTypes?

После перехода на 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)
   }
}

Что такое замена для NSFilenamesPboardType в Swift4? Как зарегистрировать тип перетаскивания file name (в моем случае mp3, wav, aiff,... files) в Swift4?

Спасибо!

4b9b3361

Ответ 1

Я решил обратную совместимость с этим расширением:

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

Ответ 2

i использую это как решение

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

    self.zipView.registerForDraggedTypes([NSFilenamesPboardTypeTemp])

это кажется ошибкой от яблока, они отмечали api как работу только в 10.13.

Я запускаю ошибку для apple:)

Ответ 3

Мне нравятся творческие обходные пути, представленные здесь для устаревшей переменной 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) }
        }
}

Поскольку параметр массива классов для readObjects имеет тип [AnyClass], это является причиной использования NSURL вместо URL.

Ответ 4

Я также сталкиваюсь с той же проблемой, и мое решение создает пользовательский NSPasteboard.PasteboardType с kUTTypeURL. Я не уверен, что это самый правильный способ (и я полагаю, нет), но он работает, по крайней мере, для временного обхода.

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

Кроме того, новый NSPasteboard.PasteboardType имеет метод .fileNameType(forPathExtension: "foo"). Вы должны попробовать. Однако почему-то это не работает в моем случае.

Ответ 5

Используя комбинацию ответа Марка Бриджеса и ответа slboat, я пришел к следующему решению:

extension NSPasteboard.PasteboardType {

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

Это работает, как и ожидалось в моем тестировании.

Ответ 6

Swift4, Swift5:

Ну, отчасти временный обходной путь, но работающий на 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))