NSTableView ViewBasedを試してみる(macos)
NSTableView CellBasedを試してみたのだが、ViewBasedという実装方法もあるらしいので、試してみた。
ディレクトリを選択したら、配下のファイルを表示させる。
のだが、なんのために使い分けるのかよくわからない。。。
関連クラスのマニュアルを一部抜粋
- NSTableViewのサブクラス化は通常必要ありません。
- その代わりに、NSTableViewDelegate プロトコルに準拠したデリゲートオブジェクトおよび、NSTableViewDataSource プロトコルに準拠したデータソースオブジェクトを使用してテーブルビューをカスタマイズします。
- または、以下のサブコンポーネントのいずれかをサブクラス化することで、実現できます。
- TableViewの振る舞いをカスタマイズするために実装するオプションメソッドのセット
- TableViewのサブクラスを作成せずに動作をカスタマイズすることができます。テーブルの行と列のビューを提供し、列の並べ替えやサイズ変更、行の選択などの機能をサポート
- NSViewのサブクラスのオーバーヘッドなしで、ビューオブジェクトにテキストや画像を表示するためのメカニズム
- セルは、NSControlクラスのほとんどで、その内部動作を実装するために使用されている
- アプリ内で描画、印刷、イベント処理などを行うための基盤
- 通常、NSViewオブジェクトを直接使用することはありません。代わりに、NSViewから派生したクラスのオブジェクトを使用するか、NSViewを自分でサブクラス化し、必要な動作を実装するためにそのメソッドをオーバーライドします。NSViewクラス(またはそのサブクラス)のインスタンスは、一般的にビューオブジェクトとして、または単にビューとして知られています
NSTableColumn を選択し idenfifer を指定 tableView メソッドが呼び出されるときに、identifer をキーに値を取得させる。
ViewBasedとか、CellBasedという切り口で切り分けるのはちょっと違う感がするな。
とりあえず、メモしておく。
import Cocoa import Foundation class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource { private static let fm = FileManager.default private var files: [File] = [] @IBOutlet weak var fileTable: NSTableView! @IBOutlet weak var directoryPath: NSPathControl! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } func numberOfRows(in tableView: NSTableView) -> Int { return files.count; } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let file = files[row] let cell = tableView.makeView(withIdentifier: (tableColumn!.identifier), owner: self) as? NSTableCellView let celval = file.get(key: tableColumn!.identifier.rawValue) cell?.textField?.stringValue = celval! return cell } @IBAction func chooseDir(_ sender: Any) { let dialog = NSOpenPanel(); dialog.title = "Choose Directory" dialog.showsResizeIndicator = true dialog.showsHiddenFiles = false dialog.allowsMultipleSelection = false dialog.canChooseDirectories = true dialog.canChooseFiles = false if (dialog.runModal() == NSApplication.ModalResponse.OK) { let result = dialog.url if (result != nil) { let path: String = result!.path directoryPath.url = URL(fileURLWithPath: path) self.files.removeAll() loadFiles(basePath: path) self.fileTable.reloadData() } } } private func loadFiles(basePath: String) { if !isDirectory(path: basePath) { return } files.append(File(path: basePath, name: basePath, isDirectory: true, isOn: false)) do { let fileNames = try ViewController.fm.contentsOfDirectory(atPath: basePath) for fileName in fileNames { let childPath = basePath + "/" + fileName if isDirectory(path: childPath) { loadFiles(basePath:childPath) } print("\t" + childPath) files.append(File(path: childPath, name: fileName, isDirectory: false, isOn: true)) } } catch { print(error) } } private func isDirectory(path: String) -> Bool { var isDir = ObjCBool(false) ViewController.fm.fileExists(atPath: path, isDirectory: &isDir) return isDir.boolValue } override var representedObject: Any? { didSet { // Update the view, if already loaded. } } } public class File { let path: String let name: String let isDirectory: Bool var isOn: Bool = false init(path: String, name: String, isDirectory: Bool, isOn: Bool) { self.path = path self.name = name self.isDirectory = isDirectory self.isOn = isOn } public func get(key: String) -> String? { switch key { case "path": return self.path case "name": return self.name default: return nil } } }