概要
Window 内に Finder 経由でファイルを Drag&Drop したら、ファイルパスを改行で区切って NSTextFeild に表示する。
ブログにあげたものと同じもの。
使い方
実装方法
- NSView を継承した FileDragDropView クラスを作成して、そこに一連の処理を書く
- Storyboard の NSViewController に NSView を配置して、クラスを FileDragDropView にする
- ビルドしたら完成
ソースコード
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