Swift

Swift:NSTableViewのDrag and Drop

結論から言うと、ずっと前にObjective-CでDrag and Dropを実装しようとして諦めたときに訪れたwebサイトがとても参考になりました。

それは、Drag rows inside a NSTableViewです。Appleのサンプルプログラムやほかのものも参照したのですが、このサイトの通りに実装したら自分の思っている通りのことが実現できました。

この際、NSTableViewのDrag and Dropを整理しておきます。

使ったメソッド(呼び出される順番に列挙):

  1. func tableView(aTableView: NSTableView!, writeRowsWithIndexes  rowIndexes: NSIndexSet!, toPasteboard pboard: NSPasteboard!) -> Bool
  2. func tableView(tableView: NSTableView,  draggingSession session:NSDraggingSession!,  willBeginAtPoint screenPoint:NSPoint, forRowIndexes rowIndexes:NSIndexSet!)
  3. func tableView(aTableView:NSTableView,  validateDrop info:NSDraggingInfo, proposedRow row:Int, proposedDropOperation operation:NSTableViewDropOperation) -> NSDragOperation
  4. func tableView(tableView: NSTableView!, updateDraggingItemsForDrag draggingInfo: NSDraggingInfo!)
  5. func tableView(aTableView:NSTableView,acceptDrop info:NSDraggingInfo!,
    row: Int,dropOperation operation:NSTableViewDropOperation) -> Bool
  6. func tableView(tableView: NSTableView, draggingSession session: NSDraggingSession, endedAtPoint screenPoint: NSPoint, operation: NSDragOperation)

実装したが呼び出されなかったメソッド:

  • func ExecWriteItems(wkArraySave:[NSArray], toPasteboard pasteboard: NSPasteboard)-> Bool
  • func writableTypesForPasteboard(pasteboard: NSPasteboard!) -> [AnyObject]!
  • func writingOptionsForType(type: String!, pasteboard : NSPasteboard!) -> NSPasteboardWritingOptions
  • func tableView(aTableView: NSTableView, namesOfPromisedFilesDroppedAtDestination dropDestination: NSURL!,   forDraggedRowsWithIndexes indexSet: NSIndexSet!) -> [AnyObject]!

注意が必要な事柄:

  • awakeFromNib()等で複数行を選択可能にし、Drag and Dropの初期化が必要。DraggedTypesはなぜこのvalueでないといけないのか、そこまで深く追求していません。
    xbTableView.allowsMultipleSelection = true
    xbTableView.registerForDraggedTypes([NSStringPboardType, NSPasteboardTypeString])
    xbTableView.registerForDraggedTypes([NSPasteboardTypeString])
    xbTableView.setDraggingSourceOperationMask(NSDragOperation.Copy, forLocal: true)
  • MesaClipperでは、.webarchiveファイルをNSTableView (内部的にはNSDictionary)で管理しているため、NSTableViewのDrag and Dropを実装するとき、.webarchiveファイルを動かす処理をしなければなりませんでした。これが少し面倒でした。よくあるサンプルプログラムのファイル一覧を作るDrag and Dropは、あまり参考になりませんでした(というか、それでは実装に漕ぎ着けませんでした)。
  • そういう訳で、Drag and Dropのメソッドで利用している部分は、Drag範囲、Drop位置、タイミングの3点で、そのほかは自分で力づくで実装しなければなりませんでした。
  • selectRowでどの行が選択されているかわかるようにした方がデバッグが早いかもしれません。
  • sortによってDragした行がバラけます。Drop先頭行位置はそれで変わらないか、次にどの行を表示するか等、気をつけた方がいいと思います。
  • 先程、webViewのoverrideに制御が渡って来ないことに気がつきました。NSObjectからNSTableViewに変更したことが原因かもしれません。それで、!を取ってら制御が渡ってくるようになりました。
    理由はよくわかりません。

override func webView(sender: WebView, didFinishLoadForFrame frame: WebFrame)

  • バグ修正:既に.webffileが存在するとき、表の行情報(NSTableView or NSDictinary)を今まで更新していなかったのですが、URLをURL2にセットして、これをNSDictinaryに反映させる仕様に変えたので、webffileが存在するときでも表の行情報を更新しなければならないことがわかりました。
  • マニュアル修正:今週末はマニュアルを修正して、ソースコードをアップする予定です。ただし、マンション組合の提案資料作りもしないといけないので、全部終わるかどうか?

Categories: Swift, 技術