Hiển thị dữ liệu lên TableView với Swift trong lập trình macOS
|Bài này, mình hướng dẫn bạn hiển thị dữ liệu lên TableView với Swift trên ứng dụng macOS. TableView là một trong những điều khiển phổ biến, cho phép thể hiện dữ liệu dạng bảng gồm nhiều hàng và cột.
Trong macOS, mỗi TableView là một instance của lớp NSTableView. Trên iOS, lớp tương ứng là UITableView. Nếu bạn quan tâm cách hiển thị dữ liệu lên TableView với Swift trên iOS, hãy bấm vào đây.
Mình cũng có một bài viết về chủ đề này bằng ngôn ngữ Objective-C. Nếu bạn quan tâm đến việc đổ dữ liệu lên NSTableView bằng Objective-C, hãy bấm vào đây.
Chúng ta sẽ cho hiển thị dữ liệu là một danh sách 5 sinh viên có những thuộc tính ID, Name và Address. Dữ liệu sẽ được lưu trong một mảng, sau đó, đổ vào TableView, kết quả như hình:

Hướng dẫn
- Bước 1: Từ Xcode, bấm File > New > Project…
- Bước 2: Chọn macOS > Cocoa App, bấm Next
- Bước 3:
- Nhập tên Project vào Product Name
- Language chọn Swift
- Use Storyboards: tick chọn nếu nó chưa chọn
Bấm Next và chọn nơi lưu Project.
Thiết kế giao diện
Từ Project navigator, bấm vào file Main.Storyboard. Sau đó bấm vào nút Library, tìm và kéo thả Table View vào View.
Mặc định, Xcode sẽ tạo cho bạn một Table View có hai cột. Dữ liệu của chúng ta có 3 thuộc tính, nên sẽ tạo thêm một cột cho TableView.
Ở cửa sổ Document Outline, bấm vào Table View, sau đó, ở cửa sổ Attributes inspector, chọn Cell Based cho Content Mode và 3 cho Columns.

Bạn lưu ý là bấm vào Table View chứ không phải Bordered Scroll View – Table View. Scroll View là một đối tượng có thanh cuộn. Table View nằm trong Scroll View, để khi TableView quá dài, thanh cuộn sẽ xuất hiện cho phép người dùng kéo qua lại để xem hết TableView.
Để kiểm tra chắc chắn bạn đang chọn Table View, hãy nhìn qua cửa sổ Identity inspector, chỗ Class sẽ ghi NSTableView, nếu không, bạn đã chọn sai.

Cũng từ Document Outline, bấm vào từng cột. Với mỗi cột, bạn phải thực hiện 2 thao tác, một ở cửa sổ Identity inspector, một ở Attributes inspector, như sau:
Cột 1:
- Identity inspector > Identifier: nhập studentID.
- Attributes inspector > Title: nhập ID, đây là văn bản hiển thị trên tiêu đề cột của TableView.

Cột 2: tương ứng như trên, nhập: studentName và Student Name.
Cột 3: tương ứng như trên, nhập: studentAddress và Address.
Sau khi thực hiện xong, Document Outline sẽ hiển thị cây tương tự như hình:

Tạo Connection với mã
Trong mã, chúng ta sẽ thao tác với Table View, do đó, chúng ta sẽ tạo một connection từ giao diện Table View với mã.
Bấm vào nút Assistant editor, phần viết mã của cửa sổ Xcode sẽ bị chia làm hai, một bên là Document Outline, một bên là file code. Mặc định, Xcode sẽ tìm chính xác file code tương ứng, trường hợp này là ViewController.swift, để hiển thị bên phần file code. Nếu vì lí do nào đó cửa sổ code không hiển thị file ViewController.swift, hãy bấm vào nút có hai hình tròn lồng nhau bên trên cửa sổ code và chọn Automatic:

Bấm phải Table View kéo rê chuột vào phần định nghĩa lớp ViewController của file code, bên ngoài tất cả các phương thức. Một cửa sổ popup hiện ra, nhập tên là myTableView, Connection chọn Outlet rồi bấm Connect.

Tạo lớp Student
Chúng ta sẽ tạo lớp Student, mỗi đối tượng của lớp sẽ chứa dữ liệu của một sinh viên lấy từ database. (Mình không bàn việc kết lấy dữ liệu từ database ở bài này). Lớp có 3 thuộc tính ID, Tên và Địa chỉ.
Từ cửa sổ Project navigator, bấm phải thư mục Project, chọn New File… Sau đó, chọn Swift File, đặt tên là Student.swift và viết đoạn mã sau cho file:
import Foundation class Student { var id: String = "" var name: String = "" var address: String = "" init(id: String, name: String, address: String) { self.id = id self.name = name self.address = address } }
Tạo lớp MyData
Lớp này giả lập một model trả dữ liệu từ database lên. Trong lớp này, chúng ta sẽ tạo một class method tên getStudentList trả về một mảng gồm 5 object Student.
Từ cửa sổ Project navigator, bấm phải thư mục Project, chọn New File… Sau đó, chọn Swift File, đặt tên là MyData.swift và viết đoạn mã sau cho file:
import Foundation class MyData { class func getStudentList() -> [Student] { let studentList = [ Student(id: "S01", name: "Anna K. Behrensmeyer", address: "711-2880 Nulla St Mankato Mississippi 96522"), Student(id: "S02", name: "Blaise Pascal", address: "7292 Dictum Av. San Antonio MI 47096"), Student(id: "S03", name: "Caroline Herschel", address: "191-103 Integer Rd. Corona New Mexico 08219"), Student(id: "S04", name: "Cecilia Payne-Gaposchkin", address: "P.O. Box 887 2508 Dolor. Av. Muskegon KY 12482"), Student(id: "S05", name: "Dorothy Hodgkin", address: "935-9940 Tortor. Street Santa Rosa MN 98804") ] return studentList } }
Hiển thị dữ liệu
Để đổ dữ liệu lên TableView, lớp ViewController phải implement protocol NSTableViewDataSource và định nghĩa hai phương thức:
func numberOfRows(in tableView: NSTableView) -> Int func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
Chúng ta sẽ khai báo biến myData, biến này trỏ đến dữ liệu mà chúng ta muốn sử dụng. Ngoài ra, nhờ implement NSTableViewDataSource, chúng ta cũng xác định thuộc tính datasource của TableView là self, tức ViewController.
Mở file code ViewController.swift và viết đoạn mã sau:
import Cocoa class ViewController: NSViewController { @IBOutlet weak var myTableView: NSTableView! var myData:[Student] = [] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. myData = MyData.getStudentList() myTableView.dataSource = self } override var representedObject: Any? { didSet { // Update the view, if already loaded. } } }
Đoạn trên, bạn chưa thấy mình implement protocol NSTableViewDataSource. Chúng ta sẽ implement protocol này ngay trong file này, nhưng để dễ nhìn và dễ quản lý mã, mình sẽ tạo một extension để hiện thực protocol. Bạn hình dung đại khái trong trường hợp này, chúng ta viết mã của cùng một lớp ở hai phần khác nhau.
Viết thêm đoạn mã sau vào cuối file ViewController.swift:
extension ViewController: NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return myData.count } func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { let student = myData[row] let columnIdentifier = tableColumn!.identifier.rawValue if columnIdentifier == "studentID" { return student.id } else if columnIdentifier == "studentName" { return student.name } else { return student.address } } }
Như vậy là chúng ta đã hoàn tất việc đổ dữ liệu vào TableView với Swift.
Bạn có thể tải xuống project mẫu của mình tại: https://github.com/ngthanhbinh85/Example-NSTableView-macOS-Swift
Hướng dẫn chán thật