概要
Window 内に Finder 経由でファイルを Drag&Drop したら、ファイルパスを改行で区切って NSTextFeild に表示する。
使い方
- 起動する
- Drag&Drop
- 表示される
実装方法
- NSView を継承した FileDragDropView クラスを作成して、そこに一連の処理を書く
- Storyboard の NSViewController に NSView を配置して、クラスを FileDragDropView にする
- ビルドしたら完成
ソースコード
FileDragDropView クラスだけ抽出。
import Cocoa class FileDragDropView: NSView { var acceptableTypes: Set<String> { return [NSURLPboardType] } var nonURLTypes: Set<String> { return [String(kUTTypeText)] } let filteringOptions = [NSPasteboardURLReadingContentsConformToTypesKey:["public.text"]] var label: NSTextField? override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) } override init(frame frameRect: NSRect) { super.init(frame: frameRect) setup() } required init?(coder: NSCoder) { super.init(coder: coder) setup() } override func awakeFromNib() { super.awakeFromNib() label = NSTextField(frame: NSRect(x: 20, y: 20, width: self.frame.width - 40, height: 40)) label?.stringValue = "" label?.textColor = NSColor.black self.addSubview(label!) } func setup() { self.register(forDraggedTypes: Array(acceptableTypes)) } func shouldAllowDrag(_ draggingInfo: NSDraggingInfo) -> Bool { var canAccept = false let pasteBoard = draggingInfo.draggingPasteboard() if pasteBoard.canReadObject(forClasses: [NSURL.self], options: filteringOptions) { canAccept = true } else if let types = pasteBoard.types, nonURLTypes.intersection(types).count > 0 { canAccept = true } return canAccept } override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { let allow = shouldAllowDrag(sender) return allow ? .copy : NSDragOperation() } override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool { let allow = shouldAllowDrag(sender) return allow } override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { let pasteBoard = sender.draggingPasteboard() as NSPasteboard if let urls = pasteBoard.readObjects(forClasses: [NSURL.self], options: filteringOptions) as? [URL], urls.count > 0 { label?.stringValue = "" let files = pasteBoard.propertyList(forType: NSFilenamesPboardType) as! [String] for file in files { label?.stringValue += file + "\n" } return true } else if let types = pasteBoard.types, types.contains(NSFilenamesPboardType) { label?.stringValue = "" let files = pasteBoard.propertyList(forType: NSFilenamesPboardType) as! [String] for file in files { label?.stringValue += file + "\n" } return true } return false } }
更新履歴
2017/4/27 テキスト形式のファイルのみ Drag&Drop できるようにフィルタリング処理を追加
2017/4/26 初版
参考
[macOS] [Swift3.0] Drag & Dropでファイルパスを取得
Drag and Drop Tutorial for macOS