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
}
}
}



