Swift struct + protocol 优雅的扩展方式

前言

很多时候,系统库以及一些第三方库,调用起来太麻烦,比如给一个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 {
    let base : TE
    init(_ base: TE) {
        self.base = base
    }
}

protocol TestExtensionCompatible {
    associatedtype Compatible
    var te : TestExtension { get }
    static var te : TestExtension.Type { get }
}

extension TestExtensionCompatible {
    var te : TestExtension {
        return TestExtension(self)
    }
    
    static
    var te : TestExtension.Type {
        return TestExtension.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的扩展不但使代码变得更优雅,避免和其他库的代码冲突,而且对代码管理,以及移植到其他项目使用更加方便。所以如果要扩展一些功能,十分推荐使用这种方式

你可能感兴趣的:(Swift struct + protocol 优雅的扩展方式)