Cocoa
Swift
drag&drop

[Swift][Cocoa] Drag&Drop したファイルのファイルパスを NSTextFeild に表示する

More than 1 year has passed since last update.


概要

Window 内に Finder 経由でファイルを Drag&Drop したら、ファイルパスを改行で区切って NSTextFeild に表示する。

ブログにあげたものと同じもの。


使い方


  1. 起動する

    drag-and-drop-cocoa-sample-1.png
     

     


  2. Drag&Drop

    drag-and-drop-cocoa-sample-2.png

     

  3. 表示される

    drag-and-drop-cocoa-sample-3.png


実装方法


  1. NSView を継承した FileDragDropView クラスを作成して、そこに一連の処理を書く


  2. Storyboard の NSViewController に NSView を配置して、クラスを FileDragDropView にする

  3. ビルドしたら完成


ソースコード

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