NSTableViewを使って表形式のデータを表示する方法を説明します。
NSTableViewはUIKitのUITableViewに相当するクラスですが、UITableViewと異なり複数の列を表示することができます。
ここでは各行に本の情報(タイトルと出版社)を表示する簡単なプログラムを作成します。
以下具体的な手順を説明します。
プロジェクトの作成
macOSアプリケーションを作成します。Xcodeを起動しメニューから「File > New > Project」を選択します。
▲作成するアプリの種類を選びます。「macOS」の中にある「App」をクリックします。
▲プロジェクトの情報を入力します。
- Product Name: プロジェクトの名前を入力。
- Team: 開発チームを選択。
- rganization Identifier: 組織の識別子を入力。
- Interface: インターフェイスを構築するフレームワーク。Storyboardを選びます。
- Language: 開発言語。Swiftを選びます。
- Use Core Data: Core Dataを使用するかどうか。
- Include Tests: テスト用のコードを追加するかどうか。
すべて入力したら「Next」ボタンをクリックします。プロジェクトを作成するフォルダを選び保存したら完成です。
画面の作成
プロジェクトが作成できたら「Main.storyboard」を選択します。
▲オブジェクトライブラリからTable Viewを選択してViewControllerにドロップします。
▲Table Viewをレイアウトします。サイズは任意ですがフレーム一杯のサイズに広げておくとわかりやすいと思います。オートレイアウトを利用し、Table Viewに四辺に制約をつけておきます。
次にテーブルビューの各列の識別子とタイトルを設定します。
▲Table Viewの中にある列のオブジェクト(最初はAutomaticTableColumnIdentifier.0というような名前になっています)を選択します。Identity Inspectorを開き、Identifierをそれぞれ「title」「publisher」と変更します。
▲さらにTable Viewのヘッダー部分をダブルクリックして、列の名前「タイトル」「出版社」に変更します。
ソースコードの作成
ソースコードを実装していきます。
まずアウトレットを作成します。アシスタントエディタを開いておきます。
▲Interface BuilderでTable Viewを選択し、ViewControllerのソースコードにCtrl+ドラッグします。名前は「tableView」とします。
ViewControllerにNSTableViewDataSourceとNSTableViewDelegateを実装します。NSTableViewDataSourceはテーブルにデータを供給する役割を担い、NSTableViewDelegateはテーブルで発生したイベントを処理します。
ViewController.swiftのソースコードは次のようになります。
import Cocoa
struct Book {
var title: String
var publisher: String
}
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var tableView: NSTableView!
var books = [Book]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
books.append(Book(title:"できるAppKit", publisher: "海空出版"))
books.append(Book(title:"わかるSwiftUI", publisher: "テック出版"))
books.append(Book(title:"わかるUIKit", publisher: "テック出版"))
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
// MARK: - NSTableViewDataSource
func numberOfRows(in tableView: NSTableView) -> Int {
return books.count
}
// MARK: - NSTableViewDelegate
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let identifier = tableColumn?.identifier else {
return nil
}
guard let cell = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView else {
return nil
}
let book = books[row]
if identifier == NSUserInterfaceItemIdentifier("title") {
cell.textField?.stringValue = book.title
} else if identifier == NSUserInterfaceItemIdentifier("publisher") {
cell.textField?.stringValue = book.publisher
}
return cell
}
}
実行結果は次の通りです。
各行の1列目にはタイトルが、2列目には出版社の情報が表示されます。
重要メソッド1: numberOfRows(in:)
データの行数を返すメソッドです。
// MARK: - NSTableViewDataSource
func numberOfRows(in tableView: NSTableView) -> Int {
return books.count
}
重要メソッド2: tableView(_:viewFor:row:)
各セルの情報を表示するViewを返すメソッドです。カスタムビューを使用することもできますが、ここでは標準のNSTableCellViewを使用しています。各列は引数のtableColumnのidentifierで区別することができます。
// MARK: - NSTableViewDelegate
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let identifier = tableColumn?.identifier else {
return nil
}
guard let cell = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView else {
return nil
}
let book = books[row]
if identifier == NSUserInterfaceItemIdentifier("title") {
cell.textField?.stringValue = book.title
} else if identifier == NSUserInterfaceItemIdentifier("publisher") {
cell.textField?.stringValue = book.publisher
}
return cell
}