Nếu đã đọc đến dòng này, chắc hẳn các bạn đã từng nghe đến hoặc đọc về lập trình hướng giao thức, hay còn gọi là Protocol Oriented Programing (POP). Tuy nhiên giữa lý thuyết và thực tế là một khoảng cách khá xa, và trong lập trình, cách tốt nhất để nắm vững một công nghệ đó là thực hành nó. Do vậy bài viết dưới đây, tôi sẽ cùng các bạn áp dụng POP vào một ví dụ nhỏ để hiểu rõ hơn POP là gì.
Tất nhiên đối với những người chưa biết POP là gì, bạn vẫn có thể đọc và làm theo bài viết này. Nhưng tôi khuyên các bạn nên tìm hiểu qua, ít nhất là khái niệm cơ bản của POP tại đây để hiểu rõ bài viết này hơn.
Ở bài viết này chung ta sẽ học cách sử dụng Protocol để animate những UI Component như UIButton, UILabel, hay UIImageView. Đồng thời tôi cũng sẽ chỉ cho cac bạn sự khác biệt giữa phương pháp truyền thống và phương pháp POP.
UI
Ứng dụng này có tên là "Welcome to My House Party". Tính năng của nó là kiểm tra xem bạn có được mời tới bữa tiệc của nhà tôi hay không, và bạn sẽ phải nhập code khách mời. Không có nhiều logic phức tạp đằng sau ứng dụng này. Nếu bạn ấn button, sẽ có hiệu ứng xảy ra. Ở đây chúng ta có 4 thành phần chính sẽ diễn ra hiệu ứng: passcodeTextField, loginButton, errorMessageLabel, và profileImageView
Hai hiệu ứng ở đây là: 1. Buzzing 2. Popping (Flash)

Để hoàn toàn nắm được sức mạnh của POP ở ứng dụng thực tế, hãy so sánh nó với cách làm truyền thống. Ví dụ nếu bạn muốn animate một UIButton và UILabel, bạn cần phải subclass cả 2 và thêm phương thức vào trong đó.
class BuzzableButton: UIButton { func buzz() { // Animation Logic } }
class BuzzableLabel: UIButton { func buzz() { // Animation Logic } }
Và tạo hiệu ứng buzz khi chúng ta ấn button:
@IBOutlet wear var errorMessageLabel: BuzzableButton! @IBOutlet wear var loginButton: BuzzableLabel!
@IBAction func didTapLoginButton(_ sender: UIButton) { errorMessageLabel.buzz() loginButton.buzz() }
Bạn có thấy là chúng ta đang lặp lại một số thao tác không?. Logic animation có ít nhất 5 dòng và có một cách "tốt hơn" đó là dùng extension. Vì UILabel và UIButton đều kế thừa từ UIView, chúng ta có thể thêm:
extension UIView { func buzz() { // Animation Logic } }
. Như vậy BuzzableButton và BuzzableLabel đều tồn tại phương thức buzz. Tránh được việc lặp code.
class BuzzableButton: UIButton {} class BuzzableLabel: UIButton {}
@IBOutlet wear var errorMessageLabel: BuzzableButton! @IBOutlet wear var loginButton: BuzzableLabel!
@IBAction func didTapLoginButton(_ sender: UIButton) { errorMessageLabel.buzz() loginButton.buzz() }
Như bạn thấy thì dòng label errorMessageLabel với nội dung “Please enter valid code 😂” diễn ra hiệu ứng hơn 1 lần. Nó xuất hiện và sau đó biến mờ dần. Vậy các bạn xử lý hiệu ứng này theo cách truyền thống như thế nào? Có 2 cách để làm việc này. Đầu tiên, (một lần nữa) bạn thêm một phương thức nữa vào trong UIView.
// Extend UIView extension UIView { func buzz() { // Animation Logic } func pop() { // UILabel Animation Logic } }
Tuy nhiên, nếu chúng ta thêm phương thức vào trong UIView, thì phương thức pop sẽ có thể được gọi bởi những UIComponents khác bên cạnh UILabel. Như vậy là chúng ta đang kế thừa một function không cần thiết.
Cách thứ 2 là subclass UILabel,
// Subclass UILabel class BuzzableLabel: UILabel { func pop() { // UILabel Animation Logic } }
Cách này khá ổn, tuy nhiên chúng ta sẽ phải thay đổi tên class thành BuzzablePoppableLabe để phân biệt rõ ràng hơn.
Lúc này, nếu bạn muốn thêm một method nữa vào UILabel để chỉ rõ những gì label làm, bạn sẽ phải thay đổi tên class như BuzzablePoppableFlashableDopeFancyLovelyLabe. @@!
Protocol Oriented Programming
Thay vì subclass chúng ta hãy cùng tạo một protocol trước. Ở đây tôi xin mạn phép bỏ qua chi tiết logic animation.
protocol Buzzable {}
extension Buzzable where Self: UIView { func buzz() { // Animation Logic} }
Như vậy, bất kì một UIComponents nào tuân thủ theo Buzzable protocol sẽ phải thực thi method buzz. Không như extension khi mà chỉ những ai tuân thủ protocol sẽ phải thực hiện method đó. Hơn nữa, self.UIView được dùng để thông báo rằng protocol sẽ chỉ được tuân thủ bởi UIView hoặc những phần tử kế thừa từ UIView.
Bây giờ hãy cùng áp dụng Buzzable vào trong loginButton, passcodeTextField, errorMessageLabel, and profileImageView. Khoan, thế còn Poppable thì sao? Tương tự như vậy.
protocol Poppable {}
extension Poppable where Self: UIView { func pop() { // Pop Animation Logic } }
Cái hay của POP đó là bạn có thể áp dụng phương thức pop cho mọi UIComponent mà không phải subclass chúng.
class MyImageView: UIImageVIew, Buzzable, Poppable
Như vậy, việc đặt tên cho class đã trở nên linh hoạt hơn bời vì bạn biết rõ rằng phương thức nào là thích hợp để sử dụng dựa trên protocol và tên của mỗi protocol sẽ mô tả class đó. Việc này giúp cho code chúng ta trở nên gọn gàng và tường minh hơn rất nhiều.
Tóm tắt cho những người lười đọc:
Không còn subclassing
Cơ chế đặt tên class linh hoạt
Lời kết
Protocol Oriented Programing là một trong những tính năng hay và nổi bật nhất của Swift.Hy vọng rằng qua ví dụ trên các bạn sẽ hiểu rõ hơn về Protocol Oriented Programing, qua đó tối ưu được code của mình và làm project trở nên chuyên nghiệp hơn.
Nguồn bài viết: https://medium.com/ios-geek-community/protocol-oriented-programming-view-in-swift-3-8bcb3305c427#.q04ahcnqh
Tham gia ngay khoá học lập trình iOS, hình thức học tập rất linh hoạt cho bạn lựa chọn và sẽ có mức học phí khác nhau tuỳ theo bạn chọn học Online, Offline hoặc FlipLearning(Kết hợp giữa Online và Offline). Ngoài ra bạn có thể tham gia thực tập toàn thời gian tại Techmaster để rút ngắn thời gian học và tăng cơ hội việc làm.
Bình luận