Swift自定义命名空间的学习

最近看到一篇文章,实现swift中UIView的链式调用的简单封装。
其中谈到为了防止自己在extension中声明的方法与未来UIView中新推出的方法重名或者冲突,使用了命名空间形式扩展的实现。来达到如下的效果

let label = UILabel()
    .hand.adhere(toSuperView: view)
    .hand.layout { (make) in
        make.top.equalToSuperview().offset(80)
        make.centerX.equalToSuperview()
    }
    .hand.config(labelConfiger)

其中每次具体方法调用之前都需要调用hand就是一种命名空间形式的扩展。
然后源代码如下:

public protocol NamespaceWrappable {
    associatedtype WrapperType
    var hand: WrapperType { get }
    static var hand: WrapperType.Type { get }
}

public extension NamespaceWrappable {
    var hand: NamespaceWrapper<Self> {
        return NamespaceWrapper(value: self)
    }

 static var hand: NamespaceWrapper<Self>.Type {
        return NamespaceWrapper.self
    }
}

public struct NamespaceWrapper<T> {
    public let wrappedValue: T
    public init(value: T) {
        self.wrappedValue = value
    }
}

最后附上命名空间形式下对UIView调用方法的扩展

import UIKit
import SnapKit

extension UIView: NamespaceWrappable { }
extension NamespaceWrapper where T: UIView {
    public func adhere(toSuperView: UIView) -> T {
        toSuperView.addSubview(wrappedValue)
        return wrappedValue
    }

    @discardableResult
    public func layout(snapKitMaker: (ConstraintMaker) -> Void) -> T {
        wrappedValue.snp.makeConstraints { (make) in
            snapKitMaker(make)
        }
        return wrappedValue
    }

    @discardableResult
    public func config(_ config: (T) -> Void) -> T {
        config(wrappedValue)
        return wrappedValue
    }
}

本质上,就是把类似于adhere,layout,config这样的方法从UIView的名下挪到NamespaceWrapper下,让UIView能够获取NamespaceWrapper的实例来进行间接调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容