Swift如何创建命名空间

作者: 囧书 | 来源:发表于2017-05-09 20:13 被阅读860次

相比于OC时代的完全没有命名空间,Swift可以通过巧妙的办法,实现几乎等同于命名空间的效果。

需求

现在我们希望为UIColor类增加一个扩展方法,根据其自身颜色生成图像UIImage
在没有命名空间的时代,可能结果是这样子的:

let image = UIColor.blue.image

或者为避免与其它框架API同名,可能结果会变成这样子:

let image = UIColor.blue.jx_image

当然这种风格非常地OC。

那有没有优雅一点的办法来代替OC Style?比如能写成这样子就好了:

let image = UIColor.blue.jx.image

Swift3绕一下路,也是可以做到的。姑且把中间的.jx叫做命名空间(Namespace),没错,抄了一下C#们的叫法。

定义命名空间

具体的做法通过扩展特定的协议来达到目的。
我们需要定义两个协议,其中一个是固定的写法:

/// 类型协议
protocol TypeWrapperProtocol {
    associatedtype WrappedType
    var wrappedValue: WrappedType { get }
    init(value: WrappedType)
}

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

另一个协议基本上也是固定的写法,只是根据我们的需要,更改其内的命名空间名字即可。
比如我需要一个名为jx的命名空间,就可以这样写:

/// 命名空间协议
protocol NamespaceWrappable {
    associatedtype WrapperType
    var jx: WrapperType { get }
    static var jx: WrapperType.Type { get }
}

extension NamespaceWrappable {
    var jx: NamespaceWrapper<Self> {
        return NamespaceWrapper(value: self)
    }
    static var jx: NamespaceWrapper<Self>.Type {
        return NamespaceWrapper.self
    }
}

需要什么样的命名空间,就把其中的jx改成你希望的名字。

使用命名空间

实际上我们需要扩展的类不是UIColor,而是协议。
这里分两步,第一步是让需要扩展的类遵循协议NamespaceWrappable

extension UIColor: NamespaceWrappable {}

第二步是扩展协议TypeWrapperProtocol

extension TypeWrapperProtocol where WrappedType == UIColor {
    /// 用自身颜色生成UIImage
    var image: UIImage? {
        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(wrappedValue.cgColor)
        context?.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        return image
    }
}

在扩展的方法中,self代表的是协议,而不是目标扩展类。那要用到self怎么办?用wrappedValue吧,它就是我们的目标类/实例。

验证

现在可以愉快地玩耍了:

let image = UIColor.blue.jx.image

使用了命名空间后,还有一个优点就是可以利用Xcode的代码补全。

Xcode代码补全Xcode代码补全

相比在打出.im后Xcode会弹出一大堆匹配到im两字母的方法,使用了命名空间后,点出.jx.时,Xcode就只会提示此命名空间内的方法/属性。特别是StringUIView这种有巨量方法的类,只要打出命名空间就可以快速过滤不需要的方法。

下载Demo

相关文章

  • Swift如何创建命名空间

    相比于OC时代的完全没有命名空间,Swift可以通过巧妙的办法,实现几乎等同于命名空间的效果。 需求 现在我们希望...

  • Swift 动态获取命名空间

    在swift中有时候需要动态获取命名空间,通过命名空间创建类 这里是通过命名空间创建一个视图控制器的代码

  • 2019-06-11

    命名空间 1.在swift中使用 项目的名字 +"."+"类名" 2.如何取出项目的名字并配置A类,创建A类 le...

  • kubernetes-RBAC实操

    环境准备准备test的命名空间test命名空间下创建serviceaccounttest命名空间下创建rolete...

  • Swift_通过字符串创建对应的类

    注:因为Swift新增了命名空间的概念,所以通过一个字符串来创建一个类必须加上命名空间 实现代码

  • Swift中String转Class类名

    String->Class Swift中引入了命名空间的概念,转Class需要拼接命名空间 注意Swift中引入了...

  • Python动态创建变量

    命名空间locals() 局部命名空间 globals() 全局命名空间 创建局部变量--全局不能使用 创建全局变...

  • Swift 获取命名空间

    Swift 获取命名空间 使用方法 这样便可以动态创建一个类型为myController的对象了。

  • Swift学习之通过字符串创建对象

    一、swift的空间命名机制在 Swift 中,由于可以使用命名空间了,即使是名字相同的类型,只要是来自不同的命名...

  • Swift Tips(持续更新)

    通过字符串创建类对象 在swift中打印对象时,会发现在类型前面总会有命名空间 +.+ 类名; 在swift中用字...

网友评论

    本文标题:Swift如何创建命名空间

    本文链接:https://www.haomeiwen.com/subject/eryitxtx.html