Hiển thị dữ liệu lên TableView với Objective-C trong lập trình macOS
|TableView là một trong những điều khiển phổ biến trong các ứng dụng macOS. TableView cho phép thể hiện dữ liệu dạng bảng gồm nhiều hàng và cột.
Mỗi hàng của TableView đại diện cho một đối tượng trong một bộ dữ liệu nhất định và mỗi cột hiển thị một thuộc tính cụ thể của đối tượng đó.
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 Table View 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ữ Swift. Nếu bạn quan tâm đến việc đổ dữ liệu lên NSTableView bằng Swift, hãy bấm vào đây.
Bài này, mình hướng dẫn hiển thị dữ liệu lên TableView với Objective-C. Dữ liệu hiển thị 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 NSMutableArray, sau đó, đổ vào TableView.

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 Objective-C, bên dưới có 1 checkbox Use Storyboards, click chọn nó nếu nó chưa chọn. Bấm Next và chọn nơi lưu Project.
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 mình 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.

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. Tìm file code ViewController.h, rồi bấm phải Table View kéo rê chuột vào phần @interface của file code, 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
Từ cửa sổ Project navigator, bấm phải thư mục Project, chọn New File… Sau đó, chọn Header File, đặt tên là Student.h và viết đoạn mã sau cho file:
@interface Student : NSObject @property (nonatomic, retain) NSString* studentID; @property (nonatomic, retain) NSString* studentName; @property (nonatomic, retain) NSString* studentAddress; @end
Tương tự, tạo một file Student.m (Objective-C File) và viết đoạn mã sau:
#import <Foundation/Foundation.h> #import "Student.h" @implementation Student : NSObject @synthesize studentID = _studentID; @synthesize studentName = _studentName; @synthesize studentAddress = _studentAddress; -(id)init{ self = [super init]; return self; } @end
Đây là 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ạ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 NSMutableArray gồm 5 object Student.
Tạo hai file MyData.h và MyData.m và thêm vào đoạn mã sau:
MyData.h:
#import "Student.h" @interface MyData : NSObject +(NSMutableArray *)getStudentList; @end
MyData.m:
#import <Foundation/Foundation.h> #import "MyData.h" @implementation MyData : NSObject +(NSMutableArray *)getStudentList { NSMutableArray *studentArray = [[NSMutableArray alloc] initWithCapacity: 5]; Student *std1 = [[Student alloc] init]; std1.studentID = @"S01"; std1.studentName = @"Anna K. Behrensmeyer"; std1.studentAddress = @"711-2880 Nulla St Mankato Mississippi 96522"; Student *std2 = [[Student alloc] init]; std2.studentID = @"S02"; std2.studentName = @"Blaise Pascal"; std2.studentAddress = @"7292 Dictum Av. San Antonio MI 47096"; Student *std3 = [[Student alloc] init]; std3.studentID = @"S03"; std3.studentName = @"Caroline Herschel"; std3.studentAddress = @"191-103 Integer Rd. Corona New Mexico 08219"; Student *std4 = [[Student alloc] init]; std4.studentID = @"S04"; std4.studentName = @"Cecilia Payne-Gaposchkin"; std4.studentAddress = @"P.O. Box 887 2508 Dolor. Av. Muskegon KY 12482"; Student *std5 = [[Student alloc] init]; std5.studentID = @"S05"; std5.studentName = @"Dorothy Hodgkin"; std5.studentAddress = @"935-9940 Tortor. Street Santa Rosa MN 98804"; [studentArray addObject:std1]; [studentArray addObject:std2]; [studentArray addObject:std3]; [studentArray addObject:std4]; [studentArray addObject:std5]; return studentArray; } @end
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:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView; - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
Chúng ta cũng 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.
Viết đoạn mã sau cho file ViewController.h:
#import <Cocoa/Cocoa.h> #import "Student.h" #import "MyData.h" @interface ViewController : NSViewController <NSTableViewDataSource> { NSMutableArray *myData; } @property (weak) IBOutlet NSTableView *myTableView; @end
Ở file ViewController.m, chúng ta sẽ lấy dữ liệu gán vào biến myData, sau đó, xác định datasource của Table View là self, tức ViewController là nguồn xử lý dữ liệu cho TableView. Cuối cùng, hiện thực hai phương thức như trên đã nói để hiển thị dữ liệu lên TableView:
#import "ViewController.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. myData = MyData.getStudentList; _myTableView.dataSource = self; } - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; // Update the view, if already loaded. } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return myData.count; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { NSString *columnIdentifier = [tableColumn identifier]; if ([columnIdentifier isEqualToString:@"studentID"]) { return [[myData objectAtIndex:row] studentID]; } else if ([columnIdentifier isEqualToString:@"studentName"]) { return [[myData objectAtIndex:row] studentName]; } else { return [[myData objectAtIndex:row] studentAddress]; } } @end
Như vậy là chúng ta đã hoàn tất việc đổ dữ liệu vào TableView.
Bạn có thể tải xuống project mẫu của mình tại: https://github.com/ngthanhbinh85/Populating-the-NSTableView-MacOS-Objective-C