前语

我报名参加金石计划1期应战——分割10万奖池,这是我的第1篇文章,点击查看活动详情

咱们平时用swift写第三方扩展(OC中的分类)时,可能会直接就往扩展里边写办法,简略又便利,然而当咱们看一些常用你的三方(例如:Kingfisher、SnapKit)等,都会用一个简略的参数引出(例如:kfsnp),下面来探索一下怎样用的,然后在总结其优缺点

SnapKit扩展办法扼要考虑

SnapKit为例,运用如下,发现引进了 snp

var iv = UIImageView();
iv.snp.makeConstraints { make in
}

中心变量 snp 如下所示,ConstraintView是一致不同渠道的重命名(别号)

public extension ConstraintView {
    var snp: ConstraintViewDSL {
        return ConstraintViewDSL(view: self)
    }
}

其曾经版别也是直接将 left 等加上前缀 snp_,直接调用,而参加前缀我想咱们一眼就看出来意图了,没错避免与其他扩展重名,现在也已经改成了引进snp的办法,来直接调用,实践逻辑都经过 snp 来调用,个人猜想也是学习了主流的应用来更新的,调用时,至少分类 API 整洁了

优缺点

  • 1、引进中心变量 snp 之后,首要感觉到的便是,咱们的分类在调用的时分,显着没有那么多杂乱的办法了(这种办法OC其实也能够学习)
  • 2、别的也能够取消了前缀,减少了代码量,并且当与其他类呈现重名的时分,只需要替换 snp 的变量姓名即可,不需要替换悉数办法,减少了命名阻止
  • 3、不同三方之间经过引进该参数,让咱们的调用模块标识更显着,功用模块也更明晰,可维护性更强

Kingfisher扩展办法扼要考虑

Kingfisher为例,运用如下,发现引进了 kf

var iv = UIImageView();
iv.kf.setImage(with: URL(string: "http://www.baidu.com"))

别的其在运用过程中,经过充分利用 swift 特性,比 SnapKit 运用上更高雅高效一些

//声明一个根底协议,有必要为 AnyObject 类型,可用于后续给根底类添加协议
public protocol KingfisherCompatible: AnyObject { }
//扩展实现该根底协议,以便于便利让咱们的组件能够直接经过 .kf 直接调用里边的办法
//此 kf 和 snap 相似,只不过添加了一个泛型,用于不同类之间进行扩展约束
extension KingfisherCompatible {
    public var kf: KingfisherWrapper<Self> {
        get { return KingfisherWrapper(self) }
        set { }
    }
}
//经过泛型顶一个一个根底类,经过该根底类能够获取咱们被扩展的组件
//且经过该根底类的泛型,能够分别给不同类型添加不同扩展办法
public struct KingfisherWrapper<Base> {
    public let base: Base
    public init(_ base: Base) {
        self.base = base
    }
}
//当遵从协议的类为 UIImage 的时分,为其扩展办法
extension KingfisherWrapper where Base: KFCrossPlatformImage {
    ...
}
//当遵从协议的类为 KFCrossPlatformImageView 的时分,为其扩展办法
extension KingfisherWrapper where Base: KFCrossPlatformImageView {
    ...
}
...
//上面仅仅是界说了一个扩展后能够运用的协议,并未应用到咱们的根底组件中
//因此只需要给根底组件添加扩展,遵从咱们的协议即可
extension KFCrossPlatformImageView: KingfisherCompatible { }

没见到姓名的View 是为了不同渠道一致姓名起的别号,如下所示(消除疑虑专用)

#if os(iOS) || os(tvOS)
    public typealias ConstraintView = UIView
#else
    public typealias ConstraintView = NSView
#endif

优缺点:

  • 1、引进中心变量 kf 之后,首要感觉到的便是,咱们的分类在调用的时分,显着没有那么多杂乱的办法了(这种办法OC其实也能够学习)
  • 2、别的也能够取消了前缀,减少了代码量,并且当与其他类呈现重名的时分,只需要替换 kf 的变量姓名即可,不需要替换悉数办法,减少了命名阻止
  • 3、不同三方之间经过引进该参数,让咱们的调用模块标识更显着,功用模块也更明晰,可维护性更强
  • 4、引进协议和泛型,经过协议一致引进同一个中心变量,经过泛型给不同的分类扩展出不同的办法,减少无效办法和代码等,结构更明晰,某种角度上,其为进阶版的扩展办法

自行仿照尝试

public protocol MarshalTest: AnyObject {}
struct Wrapper<T>  {
    public let base: T
    init(_ base: T) {
        self.base = base
    }
}
extension MarshalTest {
    var ml: Wrapper<Self> {
        get { Wrapper(self) }
        set { }
    }
}
extension UIImageView : MarshalTest {}
extension Wrapper where T: UIImageView {
    func setImg() {
    }
}
extension Wrapper where T: UIView {
    func setBkg() {
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        var iv2 = UIImageView()
        iv2.ml.setImg()  
    }
}

这就测试成功了,咱们仿照时,就能够参考这个写

最终

当咱们自己为默认组件扩展内容时,假如只扩展一个类和功用,能够像 snp 相同,直接引进中心变量扩展即可,假如咱们的扩展了多个分类,而隶属于一个模块,那么能够仿照 Kingfisher,让咱们的功用更明晰