頭と尻尾はくれてやる!

iOSアプリなどの開発日記です


macOSで同一アプリ内でtableからviewへドラッグ&ドロップする



↑このようにmacOS内のtableの表示項目(ファイル名とか)をドラッグし、NSViewオブジェクト部分へドロップする。

    func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) 
-> NSPasteboardWriting? {

return imageNames[row] as NSString
}
↑NSTableViewDataSourceのメソッドで何がドラッグ&ドロップされるのかを記述する。

    override func performDragOperation(_ draggingInfo: NSDraggingInfo) 
-> Bool {

let pasteBoard = draggingInfo.draggingPasteboard

let point = convert(draggingInfo.draggingLocation, from: nil)


if let strings = pasteBoard.readObjects(forClasses: [NSString.self],
options: nil) as? [String] {
processImages(strings, center: point)
}
return true
}
↑するとドロップした時点でpaste boardに入ってる先ほど指定した型のオブジェクトを得ることができる。


YamaguchiTatsuya/DragAndDrop_TableToView: masOS sample code to drag and drop files from NSTable to NSView object
↑GitHubに置いたサンプルコードはこちら。



macOS 10.15.2 Catalina
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする
macOSの同一アプリ内で画像などをドラッグ&ドロップする
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする(当記事)
macOSでFinderなどからtableにドラッグ&ドロップする


参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com


macOSの同一アプリ内で画像などをドラッグ&ドロップする



↑このようにNSViewオブジェクトに乗っている別なNSViewオブジェクト(ここでは画像)をマウスで動かしたい。

元々iOSで似たようなことをやってるコードがあったのでmacOS用に移植した。
{
let panGestureRecognizer = NSPanGestureRecognizer(target: self,
action: #selector(self.drawView(recognizer:)))

imageView.addGestureRecognizer(panGestureRecognizer)
}
↑ジェスチャーを設定。

    @objc private func drawView(recognizer: NSPanGestureRecognizer) {

guard let targetView = recognizer.view else {
assertionFailure("targetView is nil")
return
}

let distance = recognizer.translation(in: targetView)

let newCenter = CGPoint(x: targetView.center.x + distance.x,
y: targetView.center.y + distance.y)

targetView.center = newCenter

recognizer.setTranslation(CGPoint(x: 0, y: 0), in: targetView)
}
↑そのジェスチャーを拾う部分。
ほとんどiOSと同じなんだけど、他にmacOSならではのやり方があるのかも?


YamaguchiTatsuya/DragAndDrop_InView: masOS sample code to drag and drop an image in NSView object
↑GitHubに置いたサンプルコードはこちら。



macOS 10.15.2 Catalina
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする
macOSの同一アプリ内で画像などをドラッグ&ドロップする(当記事)
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする
macOSでFinderなどからtableにドラッグ&ドロップする


参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com



macOSでFinderなどからviewにドラッグ&ドロップする

macOSでのドラッグ&ドロップを実装してみた。
まずFinderやデスクトップからmacOSアプリへのドラッグ&ドロップの場合。



↑こんな感じでアプリ外からアプリ内のNSViewオブジェクト領域へドラッグ&ドロップするという動作。


Drag and Drop Tutorial for macOS | raywenderlich.com
↑参考にしたのはこちら。
ただ現在のSwift 5.1.3だと動かなかったこともあり、自分が理解できるように書き換えた。


いくつかのサンプルコードを見たがドロップするところのviewはNSViewのサブクラスとしてクラスのファイルを作成している。そこに
registerForDraggedTypes([.fileURL])
と記述しておくとドロップを受け付けてくれる。

optional func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation
override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool
override func performDragOperation(_ draggingInfo: NSDraggingInfo) -> Bool
↑といったメソッドでどんなファイルがドラッグされてドロップしようとしてるのか、ドロップされたタイミングなどを取得できる。


YamaguchiTatsuya/DragAndDrop_OtherToView: masOS sample code to drag and drop files from other app to NSView object
↑GitHubに置いたサンプルコードはこちら。
マウスがドロップできるview上に来ると枠が表示される、といった機能は省いている。



macOS Catalina 10.15.2
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする(当記事)
macOSの同一アプリ内で画像などをドラッグ&ドロップする
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする
macOSでFinderなどからtableにドラッグ&ドロップする

参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com


macOSでバインドを使いテーブルを表示する

macOSでテーブルを表示させようとした。
NSTableViewDelegate、NSTableViewDataSourceを使わずにバインドを使う。
NSArrayControllerで検索するといろいろと参考ページが見つかると思う。

この方法は以前Objective-Cでやったことがあったのだが、今回はSwiftでやろうとしたらえらくはまってしまった。はまりすぎて、俺の理解がおかしいのか?とObjective-Cに戻ってまで確認したりもした。

YamaguchiTatsuya/NSTableViewWithBindings: Simple sample code for macOS, to show table view with bindings
↑とりあえず最小限のサンプルコードをGitHubで公開してみた。


NSArrayControllerをドラッグ&ドロップする

↑Interface builderでViewControllerにArrayControllerを追加(矢印のようにドラッグ&ドロップ)。

NSArrayController追加後の画面

↑ここに見えるので、これを選択して
1. outletを接続
2. Content ArrayをViewControllerのpropsArrayに設定

すると、ViewController内の以下のコードのように
        let tp1 = TableProps(name: "apple")
let tp2 = TableProps(name: "banana")
let tp3 = TableProps(name: "chocolate")

assert(arrayController != nil, "arrayController is nil")

arrayController?.addObject(tp1)
arrayController?.addObject(tp2)
arrayController?.addObject(tp3)

for tp in propsArray {
print(tp.name)
}

↑arrayControllerにデータを突っ込んだ直後にpropsArrayの中身を確認すると、ちゃんと表示されている!バインディングすげー!って感心しました。


テーブルで表示するには他にもテーブル周りでバインドを設定する必要がありますがサンプルコードでご確認ください。


なお、結局Objective-Cで動いたのにSwiftで動かず、
this class is not key value coding-compliant for the key name.
といったエラーばかり出てたのは、TablePropsクラスで@objc dynamic というのが必要だったためのようでした。

//var name: String = “” 実行時エラー
@objc dynamic var name: String = “”


Version
Swift 5.1.3


独自ファイル形式のDocument Based Applicationのサンプルコード

macOSのDocument Based Applicationの公式サンプルコードの謎
↑この続き。

AppleのサンプルコードやXcodeのデフォルトのプロジェクトではファイルを.txtファイルとして保存・読み込みする。
実際にmacOSのdocument based applicationを作成する場合にStringオブジェクトだけ扱う、なんてことはなく、様々な型のデータを扱うことになる。
そういう場合のコードを作成し、サンプルコードをGitHubで公開してみた。

YamaguchiTatsuya/DocumentBasedAppWithOwnExtension: macOS sample code for document-based application for own extension

↑こちらで適当なところから git clone https… とかで見ることができるはず。

textの場合と異なるのはContextクラスをNSSecureCodingプロトコルに準拠するようにした、というくらいか。




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.