一个包含所有扩展方法的Swift模块

时间:2018-09-20 10:53:16

标签: swift extension-methods rx-swift swift-protocols

个人而言,我更喜欢Swift中带前缀的扩展方法。乍一看,可以更轻松地猜测函数是来自原始类还是来自扩展。而且,它使框架在其他项目中更可重用。我们不需要搜索框架方法所属的名称空间。但是,在扩展中的所有实例和静态方法中添加前缀有点穷举。因此,我想创建一个包含所有扩展方法的模块,无论它是实例方法还是静态方法。

我看过this implementation并喜欢它,但不幸的是,它仅适用于实例方法:

Install-Module MSOnline  

使用此方法,我们可以按以下方式访问实例方法:

public protocol MyHelperCompatible {
    associatedtype someType
    var my: someType { get }
}

public extension MyHelperCompatible {
    public var my: MyHelper<Self> {
        get { return MyHelper(self) }
    }
}

public struct MyHelper<Base> {
    let base: Base
    init(_ base: Base) {
        self.base = base
    }
}

// All conformance here
extension UIColor: MyHelperCompatible { }

您知道一种应用类似逻辑来添加模块以处理实例方法和静态方法的方法吗? (例如let redImage = UIColor.red.my.toImage() ),您建议使用哪种方式解决此问题?

1 个答案:

答案 0 :(得分:2)

受RxSwift所采用的方法的启发,此解决方案可访问my扩展的实例和静态成员。

首先,让我们声明扩展的基础:

struct MyExtension<Target> {
    let target: Target

    init(_ target: Target) {
        self.target = target
    }
}

让我们允许类型符合

protocol MyExtensionCompatible { }

extension MyExtensionCompatible {
    // instance extension
    var my: MyExtension<Self> { return MyExtension(self) }

    // static extension
    static var my: MyExtension<Self>.Type { return MyExtension<Self>.self }
}

现在开始播放并添加UIColor一致性:

extension UIColor: MyExtensionCompatible { }

extension MyExtension where Target == UIColor {

    static var customColor: UIColor { return UIColor.blue }

    func toImage() -> UIImage {
        return UIImage()
    }
}

最后,让我们使用上面创建的所有内容:

// the static property
let color = UIColor.my.customColor

// the instance function
let colorImage = color.my.toImage()

// foldoesn't compile, compile, we haven't declared UILabel as compatible
let color2 = UILabel.my

上述方法的优点在于,声明为static的方法可以通过static协议属性使用,而实例方法可以通过instance协议属性使用。