前言
很多时候,系统库以及一些第三方库,调用起来太麻烦,比如给一个View设置阴影,需要写几行代码:
view.layer.shadowColor = UIColor.red.cgcolor
view.layer.shadowOffset = .zero
view.layer.shadowOpacity = 0.5
view.layer.shadowRadius = 2
如果每个view都写这样的代码,就会显得很傻,很臃肿,所以我们一般都会给UIView扩展出一个方法:
extension UIView{
func setShadow(_ color: UIColor?,
offset: CGSize,opacity: Float,radius: CGFloat){
layer.shadowColor = color?.cgColor
layer.shadowOffset = offset
layer.shadowOpacity = opacity
layer.shadowRadius = radius
}
}
这样每次设置阴影就调用这个方法就可以了。
但是,有时候一些第三方库,或者项目的其他开发人员在UIVIew也扩展了一个叫setShadow的方法,而且参数完全一样,只是方法的内容并不同,效果也不是你想要的,这时你又不想换另一种可能引起歧义的方法名,这时你就可以使用struct + protocol 的扩展方式。
一、创建项目或自己的专属extension类
struct + protocol的扩展方式是swift泛型的一个灵活运用,很多优秀的第三方库(如RxSwift,Kingfisher)都使用了这种扩展方式,这种方式最大的优点是可以避免和其他库的冲突,还有些其他的优点如管理方便只是附加的。
下面是实现代码:
struct TestExtension<TE> {
let base : TE
init(_ base: TE) {
self.base = base
}
}
protocol TestExtensionCompatible {
associatedtype Compatible
var te : TestExtension<Compatible> { get }
static var te : TestExtension<Compatible>.Type { get }
}
extension TestExtensionCompatible {
var te : TestExtension<Self> {
return TestExtension(self)
}
static
var te : TestExtension<Self>.Type {
return TestExtension<Self>.self
}
}
简单的几行代码就建立了一个属于项目或自己的扩展类,下面我们利用这个类去扩展UIView的阴影设置。
二、扩展UIView
直接上代码:
extension UIView : TestExtensionCompatible{}
extension TestExtension where TE : UIView{
func setShadow(_ color: UIColor?,
offset: CGSize,
opacity: CGFloat,
radius: CGFloat) {
base.layer.shadowColor = color?.cgColor
base.layer.shadowOffset = offset
base.layer.shadowOpacity = Float(opacity)
base.layer.shadowRadius = radius
}
}
首先给UIView继承协议 TestExtensionCompatible,然后在TestExtension的扩展里实现setShadow的方法,注意where TE : UIView这里,也可以是TE == UIVIew,用“ == ”会限制了扩展里的方法只能给UIVIew使用,而用“:”的话UIVIew的子类也可以使用扩展里的方法。
调用:
let view = UIView()
view.te.setShadow(.black, offset: .zero, opacity: 0.5, radius: 2)
总结
struct + protocol的扩展不但使代码变得更优雅,避免和其他库的代码冲突,而且对代码管理,以及移植到其他项目使用更加方便。所以如果要扩展一些功能,十分推荐使用这种方式