也不知道何时冒出了面向协议编程,很多文章都开始大谈面向协议编程,抛弃了之前都还畅谈面向对象编。也许一个技术用久了,就会渐渐表现出其不足之处,当这种不足让人无法忍受,就会去寻找新的解决方法,来弥补现在的不足,一个新的事物也就因此而诞生。
面向对象,从开始接触编程开始就要求用面向对象的思想去设计代码,当类之间的关系变得越来复杂,类之间的继承层级越来越深,就会出现类似树形结构,当我们想重用树形末端的代码时,不得不把上层直至树根的代码一起添加,也不管有用没用的代码。面向协议编程,我的理解就是解除这种情况的出现,把功能分散开来,通过组合的方式来创建出一个类,让这个类拥有它应该有的功能,分散出来的功能也可以在其他地方复用,不会引入过多的不必要的的代码,当然这个取决于功能的粒度大小。
swift恰好支持面向协议编程特性,自己还需要从面向对象中走出了,认真理解,学习面向协议,更重要的是在实践中去应用。下面就是对面向协议的一个简单窥探吧,体验它的好处
初体验
这是一个简单的demo。先看图:
当点击登录按钮,两个输入框及按钮都会左右抖动,然后一行提示文字渐渐显示,最后在慢慢消失。可能最开始拿到这个需求,要么在点击按钮的时候分别对控件进行动画控制或者自定义控件中添加动画功能,这样要么在控制器会有很多代码,要么同样一个抖动动画代码会出现在自定义的输入框代码中,也会出现在自定义按钮的代码中。本着不要重复造轮子的原则,面向协议就会很好解决这些问题。
1.自定义这三种控件的类,以此来添加动画特效
// 自定义的输入框类,遵守抖动协议
class SP_TextField: UITextField, SharkAnimation {
}
// 自定义的按钮类,遵守抖动协议
class SP_Button: UIButton,SharkAnimation {
}
// 自定义label类,遵守渐变协议
class SP_Label: UILabel, FlashAnimation {
}
2.定义两个协议
// 左右抖动协议
protocol ShakeAnimation {
}
// 由于动画是加在view上的,所以要保证遵守的协议类必须是继承自UIView,所以使用where限制
extension ShakeAnimation where Self : UIView {
//抖动的方法的默认实现
func shake() {
let shakeAni = CAKeyframeAnimation(keyPath: "transform.translation.x")
shakeAni.values = [-8,0,8,0]
shakeAni.duration = 0.25
shakeAni.repeatCount = 5
self.layer.add(shakeAni, forKey: nil)
}
}
// 渐变的协议
protocol FlashAnimation {
}
// 同样需要遵守的类是继承自UIView的类
extension FlashAnimation where Self : UIView {
// 渐变方法的默认实现
func flash() {
UIView.animate(withDuration: 0.25, animations: {
self.alpha = 1.0
}) { (isFinished) in
UIView.animateKeyframes(withDuration: 0.25, delay: 2.0, options: [], animations: {
self.alpha = 0.0
}, completion: nil)
}
}
}
3.在控制器中使用
class ViewController: UIViewController {
@IBOutlet weak var nameTextField: SP_TextField!
@IBOutlet weak var passwordTextField: SP_TextField!
@IBOutlet weak var tipLabel: SP_Label!
@IBOutlet weak var loginButton: SP_Button!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 按钮点击事件
@IBAction func buttonClick(_ sender: SP_Button) {
// 点击时直接调用就可以了
nameTextField.shake()
passwordTextField.shake()
tipLabel.flash()
loginButton.shake()
}
}
4.如果以后还有其他控件,直接遵守协议,就拥有了抖动或者渐变的功能,是不是感觉很爽,很方便,复用性也强。当然这个功能的粒度需要自己掌控
这个是在学习中看到的一个示例,自己实现了一遍,是不是感觉很爽,拥抱面向协议吧。
独立思考,不屈从世界,安静内心,疯子一样行动,不理会周遭的嘈杂,有节奏的行走在coding~