先日、NSTableViewで作ったテーブルビューにセルを追加する方法を紹介しました。
その中で軽く触れたのですが、この記事で紹介した方法は同一ビューの中でしか機能しません。
別のビューからセルを追加するとエラーになるので、今回は別のビューからでもNSTableViewにセルを追加する方法を紹介します。
もくじ
はじめに
前回同様、今回の記事でもSwiftとXcodeを使用しています。
インストールなどについては触れませんので、あらかじめ済ませておいてください。
前回の記事を確認していない方は、先にこちらから確認しておきましょう。
今回作成するアプリケーションと前回の記事で紹介した内容がかぶっている場合、一部省略する可能性があります。
【Swift】テーブルビューにセルを追加するNSTableViewの使い方 - クリアメモリ
こちらの記事で、NSTableViewにセルを追加する方法を紹介してるのですが、別のビューから追加しようとするとエラーが発生します。
例えば、ポップオーバーしたウィンドウからセルを追加しようとするとエラーが発生してしまうんですよね。
そこで今回は、以下のような形でNSTableViewにセルを追加する方法を紹介します。
今回の流れ
今回の流れは以下のようになっています。
- ストーリーボードを作成
- ビューをpopoverで接続
- コードからNSTableViewの値を取得
- 別ビューからテキストの内容を取得
- NotificationCenterで通知
- 通知を受けたらNSTableViewを更新
- セルが追加される
このような順でストーリーボードやコードを作成していきます。
ではまず、ストーリーボードにTableViewや別のビューなどを配置していきましょう。
ストーリーボードを作成
今回作成するアプリケーションで必要になるオブジェクトは以下のものになります。
- TableView (Cell Based)
- Button (Popover)
- View (Another View)
- Label (Name and Age)
- TextField (Text)
- Button (Append)
では順番に作成していきましょう。
TableViewを配置
まずは、前回同様「TableView」をストーリーボード上に配置してください。
今回は「コラム数: 2」「ContentMode: Cell Based」で作成しました。
TableViewのTable Header Viewには「Name」と「Age」を指定しておきましょう。
ここで作成したコラムにそれぞれ「Identtifier」を設定する必要があります。
作成したコラムを選択した状態で、Identity inspectorを開いて「Identtifier」を以下のように編集してください。
これがないと後で紹介するコードで、入力が名前なのか年齢なのか判断できなくなります。
また、TableViewではデータソースを使用するので、dateSource接続しておいてください。
別のビューを呼び出すボタン
続いて、別のビュー(以下 > ビュー2)を表示するためのボタンを作成します。
今回は「+」と書かれたボタンをクリックすることで、ビュ-2がポップアップ表示されるようにしてみました。
( 設定方法はビュー2作成後に解説します)
ビュー2を作成
ビュー2では、名前と年齢を入力するウィンドウを表示させます。
以下の画像を参考にして、ビューを完成させてください。
NameとAgeに入力された文字列が、先ほど作成したTableViewのセルになります。
+ボタンとビュー2を接続
+ボタンをクリックした時にビュー2が表示されるようにするには「+ボタンからビュー2にセグエ」で接続してください。
ボタンからビューに接続すると「Action Segue」という項目が表示されるので、その中から「Popover」を選択しておきましょう。
このような表示になったかと思います。
ビュー2を表示する設定はこれだけです。
これでストーリーボードが完成しました。
アウトレット接続やアクション接続については、コードを書く時に一緒に説明します。
コードを書く
では実際にコードを作成しましょう。
今回は「ViewController」「Member」「AddMemberLiset」というクラスをそれぞれ作成してみました。
先に今回作成したコードを紹介した後で、順番に解説していきます。
ViewController -> TableViewを管理
import Cocoa
class ViewController: NSViewController, NSTableViewDataSource{
@IBOutlet weak var tableView: NSTableView!
var member =
[
Member(name: "Yamada", age: 21),
Member(name: "Sato", age: 19),
Member(name: "Suzuki", age: 25)
]
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(nCenter), name: NSNotification.Name("AddMember"), object: nil)
}
override var representedObject: Any? {
didSet {}
}
// NotificationCenter >>>
func nCenter(notification: Notification){
let addMember = notification.userInfo?["member"]
member.append(addMember as! Member)
tableView.reloadData()
}
// tableview datasource >>>
func numberOfRows(in tableView: NSTableView) -> Int {
return member.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
let columns = tableColumn?.identifier
if columns == "Name"{
return member[row].name
}else if columns == "Age"{
return member[row].age
}
return ""
}
}
今回のコードはこのようになりました。
では順番に解説を確認してください。
解説
作成したTableViewの表示や追加後の更新、NotificationCenterなどを記述してあります。
ViewControllerの配列memberに追加する値を初期化させるクラスです。
AddMemberList ->
TableViewに名前と年齢に入力された文字列を取得しセルを追加します。
ViewControllerの解説
まずはTableViewをアウトレット接続しています。
@IBOutlet weak var tableView: NSTableView!
続いて、配列memberの中に初期状態で表示する項目を追加しておきました。
これは空白でも構いません。
viewDidLoad( )ではNotificationCenterに通知を追加しています。
addObserver( )で通知の名前や、セレクタなどを指定する必要があり、NSNotification.Nameは後述するPostで設定した名前と同じにしてください。
NotificationCenter.default.addObserver(self, selector: #selector(nCenter), name: NSNotification.Name("AddMember"), object: nil)
nCenterでは通知を受けた時の処理を記述します。
// NotificationCenter >>>
func nCenter(notification: Notification){
let addMember = notification.userInfo?["member"]
member.append(addMember as! Member)
tableView.reloadData()
}
先ほど同様、userInfo[ ]の文字列もNotificationCenter.default.postで設定したものと同じにしてください。
tableView( )では、先ほど設定したコラムのIdentifier (Identity) を判定しています。
let columns = tableColumn?.identifier
if columns == "Name"{
return member[row].name
}else if columns == "Age"{
return member[row].age
}
return ""
コラムのIdentityがNameなら…
コラムのIdentityがAgeなら…
Memberの解説
ViewControllerのMember( )では、名前と年齢をひとまとめにして配列に追加していました。
そのMemberをこのクラスで定義しました。
この記述がないと、ViewControllerはエラーになるので注意。
また、以下の画像にあるように「Target Membership」のプロジェクトにチェックが入っていることを確認してください。
※作成したプロジェクト名によって表示される内容は異なります。
AddMemberListの解説
最後にAddMemberListの解説になります。
このコードの中では、Appendボタンがクリックされたら「NotificationCenterに通知」を送るようになっています。
@IBAction func appendButton(_ sender: NSButton) {
let nameString = nameText.stringValue
let ageInt = Int(ageText.stringValue)
if nameString != "" && ageInt != nil{
let member = Member(name: nameString, age: ageInt!)
NotificationCenter.default.post(name: NSNotification.Name("AddMember"), object: nil, userInfo: ["member": member])
nameText.stringValue = ""
ageText.stringValue = ""
}
}
名前と年齢のテキストフィールドが空白ではない場合、ViewControllerに通知を送り、テーブルビューをリロードさせています。
このようにすることで、別のビューからでもテーブルビューを更新させることができました。
まとめ
今回紹介したように、テーブルビューに別のビューからセルを追加するには、NotificationCenterを使用することで実装できました。
これで、決まった内容のテーブルビューだけではなく、ユーザーが追加した項目を反映させることができますね。
とはいっても、保存処理を記述していないので、アプリを終了すると消えてしまいますが。
NSTableViewやNotificationCenterはとても便利なので、ぜひ活用してみてください。
ではまた。