欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Swift使用SnapKit模仿Kingfisher第三方扩展优化,

来源: 开发者 投稿于  被查看 19562 次 评论:244

Swift使用SnapKit模仿Kingfisher第三方扩展优化,


目录
  • 正文
    • SnapKit扩展方式简要思考
    • Kingfisher扩展方式简要思考
    • 自行模仿尝试
  • 最后

    正文

    我们平时用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,让我们的功能更清晰

    以上就是Swift SnapKit模仿Kingfisher第三方扩展优化示例的详细内容,更多关于SnapKit第三方扩展的资料请关注3672js教程其它相关文章!

    您可能感兴趣的文章:
    • swiftui开发之padding默认值设置详解
    • SwiftUI 引导页界面实现示例
    • SwiftUI 登录界面布局实现示例详解
    • swift语言Codable 用法及原理详解
    • swift语言AutoreleasePool原理及使用场景
    • Swift 并发修改Sendable 闭包实例详解

    用户评论