2015-07-27 11 views
9

come implementare una zona di trascinamento della selezione in swift 2.0?os x Swift: ottieni il percorso file utilizzando il trascinamento della selezione

Ho creato un'app che elabora i file kext ma, per ora, devo inserire manualmente il percorso per l'input kext. la mia domanda è: come ottenere il percorso del file eseguendo un trascinamento su una zona?

+2

possibile duplicato di [Implementazione di una zona di drag-and-drop in Swift] (http: // stackoverflow.com/questions/29233247/implementing-a-drag-and-drop-zone-in-swift) –

risposta

15

[Update per Swift 4.0 e Xcode 9]

Aggiungi un NSView alla vista principale e sottoclasse. Questo codice funziona perfettamente con Swift 4.0 e macOS 10.13 High Sierra!

import Cocoa 

class DropView: NSView { 

    var filePath: String? 
    let expectedExt = ["kext"] //file extensions allowed for Drag&Drop (example: "jpg","png","docx", etc..) 

    required init?(coder: NSCoder) { 
     super.init(coder: coder) 

     self.wantsLayer = true 
     self.layer?.backgroundColor = NSColor.gray.cgColor 

     registerForDraggedTypes([NSPasteboard.PasteboardType.URL, NSPasteboard.PasteboardType.fileURL]) 
    } 

    override func draw(_ dirtyRect: NSRect) { 
     super.draw(dirtyRect) 
     // Drawing code here. 
    } 

    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { 
     if checkExtension(sender) == true { 
      self.layer?.backgroundColor = NSColor.blue.cgColor 
      return .copy 
     } else { 
      return NSDragOperation() 
     } 
    } 

    fileprivate func checkExtension(_ drag: NSDraggingInfo) -> Bool { 
     guard let board = drag.draggingPasteboard().propertyList(forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? NSArray, 
       let path = board[0] as? String 
     else { return false } 

     let suffix = URL(fileURLWithPath: path).pathExtension 
     for ext in self.expectedExt { 
      if ext.lowercased() == suffix { 
       return true 
      } 
     } 
     return false 
    } 

    override func draggingExited(_ sender: NSDraggingInfo?) { 
     self.layer?.backgroundColor = NSColor.gray.cgColor 
    } 

    override func draggingEnded(_ sender: NSDraggingInfo) { 
     self.layer?.backgroundColor = NSColor.gray.cgColor 
    } 

    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { 
     guard let pasteboard = sender.draggingPasteboard().propertyList(forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? NSArray, 
       let path = pasteboard[0] as? String 
     else { return false } 

     //GET YOUR FILE PATH !!! 
     self.filePath = path 
     Swift.print("FilePath: \(path)") 

     return true 
    } 
} 

Per utilizzare questo codice è necessario impostare "MacOS distribuzione Target" per 10,13

screenshot

+1

Grazie M.Moro. E Apple doc è qui: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DragandDrop/Tasks/DraggingFiles.html –

+0

Come istanziare questo a livello di programmazione e più specificamente cosa passare per 'coder: NSCoder '? – fips

+1

@fips Scusa ma non ho capito la tua domanda. È anche possibile creare a livello di codice un'istanza di classe DropView o una sottoclasse di una NSView in uno Storyboard. In init? (Coder: NSCoder) non dimenticare super.init (coder: coder). –