Kích hoạt segue với UITableView khi chọn một ô – lập trình iOS với Swift và Objective-C

Mình đã có viết một bài về cách hiển thị dữ liệu lên TableView trong lập trình ứng dụng iOS bằng cả ngôn ngữ Swift lẫn Objective-C. Bài này mình hướng dẫn tiếp cách xử lý sự kiện khi có một ô được chọn bằng cách kích hoạt segue với UITableView.

Mình sẽ bắt đầu với ứng dụng hiển thị danh sách sinh viên như trong bài mình đã nói ở trên. Nếu bạn chưa có, hãy xem ở một trong hai bài sau:

Bạn có thể download dự án mẫu ở cuối 2 bài trên để tiếp tục cho bài này. Bài này mình sẽ minh họa bằng cả Swift lẫn Objective-C.

Mục tiêu của chúng ta như sau: sau khi hiển thị danh sách sinh viên, giờ nếu người dùng bấm chọn vào một sinh viên cụ thể, chúng ta sẽ mở một view khác để hiển thị thông tin chi tiết của sinh viên đó. View này cũng có một nút Done, khi người dùng xem xong thông tin chi tiết của sinh viên, họ có thể bấm Done để quay trở lại danh sách.

Tạo ViewController hiển thị chi tiết sinh viên

Mở file Main.storyboard, bấm vào nút Library và tìm kéo View Controller vào storyboard.

Trên View Controller này, chúng ta cũng sử dụng nút Library để đặt vào 3 điều khiển sau:

1. Kéo một Label vào, ở cửa sổ Attributes inspector, nhập Student Detail vào bên dưới ô thuộc tính Text Plain. Ở thuộc tính Font, chọn Style Semibold và Size 45.

Bấm nút Add New Constraints, chúng ta sẽ neo Label cố định để nó không bị nhảy lung tung trên những màn hình khác nhau.

Ở cửa sổ Add New Constraints, nhập 0 cho ô trên và 20 cho ô trái, như hình:

Bạn phải đảm bảo hai đoạn thẳng màu đỏ từ 2 ô trên nối vào ô ở giữa hiển thị. Nếu không hiển thị thì bạn bấm vào nó. Xong bấm Add 2 Constraints. Các số khác không quan trọng.

2. Tìm và kéo một Text View vào, chúng ta sẽ hiển thị chi tiết trên Text View này theo định dạng:

ID: ...
Name: ...
Address: ...

Text View là điều khiển gần giống Text Field, tuy nhiên, nó cho phép bạn có văn bản gồm nhiều hàng.

Tương tự như Label ở trên, bấm vào nút Add New Constraints, chúng ta sẽ neo Text View như sau: trái: 20; trên: 20; phải: 20. Sau đó, bấm Add 3 Constraints.

3. Cuối cùng, kéo vào View Controller một Button. Đặt thuộc tính Title PlainDone và Constraint trên 20, phải 20.

Tạo file mã xử lý cho View Controller chi tiết sinh viên

Từ cửa sổ Project navigator, bấm phải thư mục Project, chọn New File… Sau đó, chọn Cocoa Touch Class, đặt tên là DetailViewController, ô Subclass of chọn UIViewController, không chọn checkbox Also create XIB file, ô Language chọn Swift hoặc Objective-C tùy theo bạn đang sử dụng ngôn ngữ nào. Bấm Next.

Nếu bạn chọn ngôn ngữ Swift, Xcode sẽ tạo cho bạn một file DetailViewController.swift, nếu là Objective-C, Xcode sẽ tạo hai file là DetailViewController.mDetailViewController.h.

Trở lại Main.storyboard, bấm chọn View Controller chi tiết sinh viên chúng ta mới tạo ở trên. Bạn phải chắc chắn đang chọn View Controller, bằng cách nhìn qua cửa sổ Document Outline, đối tượng View Controller đang được chọn.

Với View Controller đang chọn, bấm qua cửa sổ Identity Inspector, ở ô Class, chọn DetailViewController.

Tạo connection với mã

Trong mã, chúng ta sẽ thao tác với Text View, do đó, chúng ta sẽ tạo một connection từ giao diện Text 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à DetailViewController.swift (với Swift) hoặc DetailViewController.m (với Objective-C), để 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 DetailViewController, 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:

Nếu bạn đang lập trình bằng Swift

Bấm phải Text View kéo rê chuột vào phần định nghĩa lớp DetailViewController 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à textViewStudentDetailConnection chọn Outlet rồi bấm Connect.

Nếu bạn đang lập trình bằng Objective-C

Bấm phải Text View kéo rê chuột vào phần @interface của lớp DetailViewController của file code. Một cửa sổ popup hiện ra, nhập tên là textViewStudentDetailConnection chọn Outlet rồi bấm Connect.

File DetailViewController.m của bạn lúc này sẽ như vầy:

#import "DetailViewController.h"
 
@interface DetailViewController ()
 @property (weak, nonatomic) IBOutlet UITextView *textViewStudentDetail;
 
@end
 
@implementation DetailViewController
 
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.

 }
 
@end

Tạo segue với UITableView và DetailViewController

Để xử lý sự kiện khi có một ô trên UITableView danh sách sinh viên được chọn, chúng ta sẽ tạo segue liên kết ô với DetailViewController.

Mở Main.storyboard, chọn ô prototype trong Table View danh sách sinh viên. Để chắc chắn ô được chọn, bạn nhìn qua Document Outline, ô myCell phải đang được chọn.

Bấm phải vào myCell và kéo rê chuột qua giao diện DetailViewController, một popup hiện ra, phần Selection Segue, bạn chọn Show Detail.

Sau khi chọn, một mũi tên liên kết giữa hai View Cotroller sẽ xuất hiện như hình:

Bạn bấm chọn mũi tên này và ở cửa sổ Attributes Inspector, đặt thuộc tính Identifier của nó là segueShowDetail.

Các loại segue

Khi bạn thực hiện bước trên, phần Selection Segue cung cấp cho bạn 5 lựa chọn và ý nghĩa của chúng như sau:

  1. Show: hiển thị View Controller đích và đưa nó vào statck (Last in First out) nhờ vậy có thể điều hướng quay trở lại View Controller đầu. Nếu bạn sử dụng Navigation Controller, bạn sẽ thấy rõ.
  2. Show Detail: thay thế View Controller đầu bằng View Controller đích và không cung cấp điều hướng quay lại View Controller đầu, giống như trên iPad có sử dụng Split View Controller hiển thị hai phần, danh sách bên trái và chi tiết bên phải, khi bấm vào một mục bên danh sách thì hiển thị chi tiết bên phải, và bên phải không điều hướng để quay về danh sách lẫn chi tiết hiển thị trước đó.
  3. Present Modally: hiển thị View Controller đích đè lên View Controller cũ.
  4. Present As Popover: hiển thị View Controller đích trong một popover.
  5. Custom: tự xử lý cách hiển thị của View Controller đích.

Trong ví dụ của chúng ta, bạn có thể chọn loại segue là Show hoặc Show Detail gì cũng được vì chúng ta không hiển thị thêm điều khiển khác quản lý điều hướng nên không có khác biệt mấy.

Xử lý khi ô được chọn và truyền dữ liệu giữa các View Controller

Sau khi tạo segue, khi người dùng chọn một ô, View Controller đích sẽ tự động được hiển thị mà chúng ta không phải xử lý gì. Bạn có thể bấm chạy thử và quan sát.

Việc chúng ta cần làm là xác định dữ liệu nào được chọn để gởi nó đến DetailViewController biết mà hiển thị chi tiết.

Nếu bạn đang viết mã bằng Swift

Mở file View Controller danh sách sinh viên, override phương thức prepare như sau:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
         if segue.identifier == "segueShowDetail"
         {
             // Get current selected student
             let selectedStudent = myData[myTableView.indexPathForSelectedRow!.row]
 
             // Pass it to the DetailViewController
             let controller = segue.destination as! DetailViewController
             controller.student = selectedStudent
         }
}

Phương thức prepare sẽ được gọi mỗi khi segue được kích hoạt. Chúng ta sẽ xác định nếu là segue xem chi tiết chúng ta đã tạo, thì lấy ra sinh viên được chọn từ Table View, rồi gởi nó đến DetailViewController bằng cách gán dữ liệu đó cho thuộc tính student.

Như vậy, chúng ta sẽ qua DetailViewController.swift và tạo thuộc tính student. Thêm khai báo sau vào lớp DetailViewController:

var student: Student?

Mỗi khi DetailViewController hiển thị, student sẽ được truyền dữ liệu là sinh viên được chọn từ View Controller danh sách, vì vậy, khi DetailViewController được nạp, chúng ta đã có dữ liệu sinh viên để hiển thị chi tiết. Viết đoạn mã sau cho viewDidLoad() để lấy dữ liệu hiển thị lên Text View:

override func viewDidLoad() {
         super.viewDidLoad()
 
         // Do any additional setup after loading the view.
         if let info = student {
             textViewStudentInfo.text =  "ID: " + info.id + "\n" + "Name: " + info.name + "\n" + "Address: " + info.address
         }
         
}

Nếu bạn đang viết mã bằng Objective-C

Mở file View Controller danh sách sinh viên (ViewController.m), định nghĩa phương thức prepareForSegue như sau:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
     if ([[segue identifier] isEqualToString:@"segueShowDetail"]) {
         // Get the selected student
         Student *selectedStudent = [myData objectAtIndex:[[myTableView indexPathForSelectedRow] row]];
         
         // Pass it to DetailViewController
         DetailViewController *controller = [segue destinationViewController];
         [controller setSelectedStudent:selectedStudent];
     }
}

Phương thức prepareForSegue sẽ được gọi mỗi khi segue được kích hoạt. Chúng ta sẽ xác định nếu là segue xem chi tiết chúng ta đã tạo, thì lấy ra sinh viên được chọn từ Table View, rồi gởi nó đến DetailViewController bằng cách gọi thông điệp setSelectedStudent.

Để có thể gọi được thông điệp setSelectedStudent, chúng ta cần khai báo một biến instance _student và định nghĩa thông điệp setSelectedStudent cho DetailViewController, như sau:

Viết đoạn mã sau cho file DetailViewController.h:

#import <UIKit/UIKit.h>
#import "Student.h"
 
NS_ASSUME_NONNULL_BEGIN
 
@interface DetailViewController : UIViewController {
     // This variable points to the selected student passed from the ViewController
     Student *_student;
}
 
- (void)setSelectedStudent:(Student *)student;
 
@end
 
NS_ASSUME_NONNULL_END

Và thêm đoạn mã sau trong phần implement của DetailViewController.m:

- (void)setSelectedStudent:(Student *)student {
     _student = student;
}

Mỗi khi DetailViewController hiển thị, setSelectedStudent đã được gọi bởi View Controller danh sách và _student đã được xác định, vì vậy, khi DetailViewController được nạp, chúng ta đã có dữ liệu sinh viên để hiển thị chi tiết. Viết đoạn mã sau cho viewDidLoad() để lấy dữ liệu hiển thị lên Text View:

- (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
     
     NSMutableString *displayText = [[NSMutableString alloc] initWithString:@"ID: "];
     [displayText appendString:[_student studentID]];
     [displayText appendString:@"\nName: "];
     [displayText appendString:[_student studentName]];
     [displayText appendString:@"\nAddress: "];
     [displayText appendString:[_student studentAddress]];
     
     [self.textViewStudentDetail setText:displayText];
 }

Xử lý quay trở lại View Controller danh sách khi bấm Done

Chúng ta sẽ xử lý sự kiện khi nút Done trên DetailViewController được bấm.

Mở Main.storyboard, chọn nút Done trên DetailViewController, rồi 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. Hãy chắc chắn là DetailViewController.swift hoặc DetailViewController.m (tuỳ thuộc bạn đang dùng Swift hay Objective-C ) xuất hiện bên file code.

Bấm phải chuột trên nút Done và kéo rê vào file mã, chọn ConnectionAction, Name đặt là DoneTapped, bấm Connect:

Viết đoạn mã xử lý sự kiện cho nút Done như sau:

Nếu bạn đang viết bằng Swift:

@IBAction func DoneTapped(_ sender: Any) {
     self.dismiss(animated: true, completion: nil)
}

Nếu bạn đang viết bằng Objective-C:

- (IBAction)DoneTapped:(id)sender {
     [self dismissViewControllerAnimated:true completion:nil];
}

Như vậy, chúng ta đã hoàn thành việc kích hoạt segue với UITableView.

Bạn có thể download project mẫu của mình tại Github:

  1. Cho Swift: https://github.com/ngthanhbinh85/UITableView-Segue-from-Select-Action-Swift
  2. Cho Objective-C: https://github.com/ngthanhbinh85/UITableView-Segue-from-Select-Action-Objective-C

Bình luận

Bình luận Facebook

lời bình luận