Swift自定义命名空间的学习

2017-10-20  本文已影响174人  Dreamer_做梦的人

最近看到一篇文章,实现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的实例来进行间接调用。

上一篇 下一篇

猜你喜欢

热点阅读