iOS Lab

Swift添加命名前缀

2020-09-24  本文已影响0人  梦里桃花舞倾城

Swift命名前缀

Swift的命名空间是基于模块(module),每一个module代表了一个Swift中的一个命名空间

// ModuleA.swift
// 这个文件存在于 ModuleA,非主工程 中
public class MyClass {
    class func hello() {
        print("hello from ModuleA")
    }
}

// MyApp.swift
// 这个文件存在于 app 的主 target 中
class MyClass {
    class func hello() {
        print("hello from ModuleB")
    }
}

如果我们需要在主工程(target)中,调用非主工程里的ModuleA里相同的函数hello;我们只需要加上ModuleAtarget名去访问即可。

// 使用哪个 MyClass,取决于是在哪个 target 中调用
ModuleA.MyClass.hello()

添加自己的命名空间

初级写法

声明协议Framable
public protocol Framable {
    var x: CGFloat { get set }
    var y: CGFloat { get set }
}
实现协议Framable
struct BaseFrame: Framable {
    let view: UIView
    init(view: UIView) {
        self.view = view
    }
    public var x: CGFloat {
        get { return view.frame.origin.x }
        set { view.frame.origin.x = newValue }

    }
    public var y: CGFloat {
        get { return view.frame.origin.y }
        set { view.frame.origin.y = newValue }
    }
}
实现UIView命名前缀扩展
extension UIView {
    public var cx: Framable {
        return BaseFrame(view: self)
    }
}

使用

self.view.cx.x = 10

进阶写法

以上固然可以实现命名空间前缀,但是还是不够优雅不够Swift

为此我们可以利用泛型和协议来更高效的实现命名空间

定义泛型结构体

定义一个泛型结构体,使用泛型Base

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

定义泛型协议

定义了一个 CXNameSpace协议,这个协议代表了支持 namespace形式的扩展。并利用extension为这个协议 添加了默认实现。

public protocol CXNameSpace {
   // associatedtype 相当于一个占位符,而不能表示具体的类型。具体的类型需要让实现的类来指定。
    associatedtype T
    var cx: CXKit<T> { get }
}

public extension CXNameSpace {
    var cx: CXKit<Self> {
        return CXKit(self)
    }
    static var cx: CXKit<Self>.Type {
        return CXKit<Self>.self
    }
}

实现命名空间cx扩展

extension UIView: CXNameSpace { }

extension CXKit where Base: UIView {
    
    public var x: CGFloat {
        get { return base.frame.origin.x }
        set { base.frame.origin.x = newValue }
    }
}

使用

self.view.cx.x = 10

在对CXKitextension 时, where后面的 Base 约束可以使用 ==或者 :

区别是:

上一篇 下一篇

猜你喜欢

热点阅读