web-dev-qa-db-fra.com

Swift 4: NSFilenamesPboardType non disponible. Quoi utiliser à la place pour registerForDraggedTypes?

Après la migration vers Swift4, le code suivant génère une erreur de compilation:

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

Qu'est-ce qui remplace NSFilenamesPboardType dans Swift4? Comment enregistrer le type de glisser de file name (dans mon cas, les fichiers mp3, wav, aiff, ...) dans Swift4?

Merci!

12
Vlad

J'ai résolu la compatibilité ascendante avec cette extension: 

extension NSPasteboard.PasteboardType {

    static let backwardsCompatibleFileURL: NSPasteboard.PasteboardType = {

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

    } ()

}

Ce qui signifie que vous pouvez utiliser NSPasteboard.PasteboardType.backwardsCompatibleFileURL

13
Mark Bridges

j'utilise ceci comme solution

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

    self.zipView.registerForDraggedTypes([NSFilenamesPboardTypeTemp])

cela semble un bogue d’Apple, ils marquaient l’API comme fonctionnant en 10.13 seulement.

 i fire a bug to Apple:)

10
slboat

J'aime les solutions de contournement créatives présentées ici pour la variable obsolète NSFilenamesPboardType. Après avoir examiné cette question, un moyen d'avancer avec une approche équivalente non dépréciée consiste à utiliser readObjects(forClasses:options:). Ce serait également plus sûr que WRT puisse fonctionner sur de futurs macOS. Il serait implémenté comme dans l'exemple suivant, testé avec Swift 4.1, basé sur le fait d'avoir un NSView enregistré dans un storyboard.

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

Comme le paramètre de tableau de classe pour readObjects est de type [AnyClass], c'est la raison pour laquelle on a utilisé NSURL au lieu de URL.

4
Daniel Zhang

Je rencontre également le même problème et ma solution consiste à créer un NSPasteboard.PasteboardType personnalisé avec kUTTypeURL. Je ne suis pas sûr que ce soit le moyen le plus approprié (et je suppose que non), mais cela fonctionne au moins pour la solution temporelle.

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

De plus, le nouveau NSPasteboard.PasteboardType a la méthode .fileNameType(forPathExtension: "foo"). Vous devriez essayer. Cependant, d'une certaine manière, cela ne fonctionne pas dans mon cas.

3
1024jp

En utilisant une combinaison de réponse de Mark Bridges et réponse de slboat , voici la solution que j'ai proposée:

extension NSPasteboard.PasteboardType {

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

Cela fonctionne comme prévu dans mes tests.

0
hisaac