0

Protocol Oriented Programing trong Swift qua ví dụ đơn giản

Giới Thiệu

Trước tiên mình xin tôn trọng tác giả của bài hướng dẫn này Bob Lee. Bài viết này của mình hướng dẫn lại cho các bạn hiểu hơn về POP ,điểm mạnh mẽ và chỉ ra một số điều hay về POP.


Vào chủ đề Bài toán cụ thể như thế này, mình muốn trong 1 project của mình,cụ thể hơn là 1 UIViewController, 1 Button và 1TextField của mình có khả năng buzz animation, 1 Label và 1 Button có khả năng buzz và pop animation,nhớ là1 Button và 1TexField chỉ có khả năng buzz và không có khả năng pop, 1Label và 1Button còn lại có khả năng buzz và pop

  • Extension UIView,định nghĩa 2 func buzz và pop, cũng được đấy nhưng mà thằng nào cũng có khả năng buzz và pop cả.
  • Tạo 1 protocol và class adopted protocol đó, bạn muốn class này có khả năng pop,buzz khác nhau mình chả nói,nhưng mình muốn chúng có animation giống nhau chả nhẽ cứ viết đi viết lại cái func mình phải adopted kia ư.
  • Tại sao không có 1 thằng như thế này nhỉ, mình muốn tạo 1 protocol nó có 1 func và nó có 1 func mặc định bất cứ class nào adopt protocol này có thể sử dụng nếu muốn mà không cần định nghĩa ,hoặc có thể định nghĩa lại nếu thích => thế là POP ra đời.

POP

ở đây mình tạo 1 protocol Popable có 1 func là pop,và định nghĩa func mặc định trong extension và điều kiện để sử dụng được func mặc đình này là type mà adopt protocol Popable phải có kiểu của UIView,tương tự cho protocol Buzzable.

import Foundation
import UIKit

protocol Popable {
    func pop()
}
extension Popable where Self: UIView {
    func pop() {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {self.alpha = 1}, completion: { _ in
            UIView.animate(withDuration: 0.3, delay: 2, options: .curveEaseIn, animations: {self.alpha = 0}, completion: nil)
        })
    }
}

protocol Buzzable {
    func buzz()
}

extension Buzzable where Self: UIView {
    func buzz() {
        let animation = CABasicAnimation(keyPath: "position")
        animation.duration = 0.05
        animation.repeatCount = 5
        animation.autoreverses = true
        animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - 5, y: self.center.y))
        animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 5, y: self.center.y))
        layer.add(animation, forKey: "position")

    }
}
  • Ở đây mình tạo 1 class BuzzableTextField kế thừa từ UITextField(type UIView) và adopt protocol Buzz,vì vậy mình có thể sử dụng default func được định nghĩa trong extension.
import UIKit
// UITextFieldcó khả năng buzz
class BuzzableTextFiled: UITextField, Buzzable {

}
//UIButton có khả năng buzz
class BuzzableButton: UIButton, Buzzable {

}

class BuzzableImageView: UIImageView, Buzzable {

}
//UILabel có khả năng buzz và pop
class BuzzablePopableLabel: UILabel,Buzzable, Popable {

}

class ViewController: UIViewController {
    
    @IBOutlet weak var passwordTextField: BuzzableTextFiled!
    @IBOutlet weak var loginButton: BuzzableButton!
    @IBOutlet weak var errormessageLabel: BuzzablePopableLabel!
    @IBOutlet weak var profileImageView: BuzzableImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        setUpCornerRadius()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func ditTapLogin(_ sender: Any){
    //Tại đây gọi các func animation mặc định được định nghĩa trong extension protocol
        passwordTextField.buzz()
        loginButton.buzz()
        profileImageView.buzz()
        errormessageLabel.buzz()
        errormessageLabel.pop()
    }
    
    func setUpCornerRadius() {
        profileImageView.layer.cornerRadius = profileImageView.frame.height / 2
        profileImageView.layer.masksToBounds = true
        profileImageView.layer.borderWidth = 3.0
        profileImageView.layer.borderColor = UIColor.orange.cgColor
        
        loginButton.layer.cornerRadius = loginButton.frame.height / 2
        loginButton.layer.masksToBounds = true
    }
}

Bài toán đã được giải quyết triệt để và hiệu quả


Đó là POP, việc vận dụng POP tận dụng được một số điểm sau: class có thể adopt nhiều protocol mà không cần định nghĩa nếu protocol có func default, protocol không có func default thì class phải định nghĩa. class có thể định nghĩa lại func default trong protocol nếu muốn. (Phần này mình không chắc chắn): nó có tính chất giống như đa thừa kế, class có tính chất như Abstract class(class có những func chưa định nghĩa),POP mạnh hơn OOP ở cả 4 điểm kế thừa,trừu tượng,đa hình,đóng gói. ví dụ trên đã nêu ra 3 rồi(và Swift có tới 5 access modifiers)

Ví dụ

import UIKit

protocol Bird {
    func canSwimming()
    func canFly()
    func eat()
}

extension Bird {
    func canFly() {
        print("Chim Có Thể Bay")
    }
    
    func canSwimming() {
        print("Bird Can Swimming")
    }
    
    func Sound() {
        print("Go Go")
    }
}

class ChimCanhCut: Bird {
    /// bắt buộc phải định nghĩa,do không có func default
    func eat() {
        print("Chim Canh Cut An Ca")
    }
    /// có thể định nghĩa lại hoặc không
    func canFly() {
        print("Chim Canh Cut Khong Biet Bay")
    }
    ///không cần phải định nghĩa
    ///   func canSwimming() {
    ///        print("Chim Cánh Cụt Có Thể Bơi")
    ///    }
    
    /// nếu không định nghĩa func Sound() khi gọi chim.Sound() sẽ gọi func Sound() extension của protocol và in ra Go Go
    func Sound() {
        print("12345")
    }
}

let chim = ChimCanhCut()
chim.Sound()

Link Github 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,Cảm ơn đã đọc bài viết. ,


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí