导言:
总所周知C++中是有命名空间的说法,比如我们将使用的using namespace std;我们就可以直接使用std空间下的cout,而不必每次都这样std::cout加一个std::。
Swift中是没有像C++那样显示的命名空间说法的。但是强大的Swift语言支持是可以帮我们完成的。那么为什么需要命名空间呢?有时候我们使用别人的第三方库或者我们写库来供他人使用的时候,就可能出现变量、方法等出现重名的情况。那么如果有命名空间的存在的话,就可以达到各司其职的作用。比如第三方库和你的项目中对UIView进行了扩展,可直接通过某个view.width获取宽度,但是我们项目中也进行了扩展,可能会出现编译不通过的情况。那么我们下面用命名空间来解决。
1.首先创建我们的包装类,可以看到这里是一个范型
// 包装类
struct YH<Base> {
var base: Base
init(_ base: Base) {
self.base = base
}
}
2.创建一个协议用于达到命名空间的作用
// YHSizeCompatible协议用来实现命名空间
protocol YHSizeCompatible {}
// 由于协议的声明不能有默认的实现,所以我们可以声明一个空的协议,然后通过extension来达到有默认实现的效果。
extension YHSizeCompatible {
static var yh: YH<Self>.Type { return YH<Self>.self }
var yh: YH<Self> { return YH(self) }
}
3.比如这里我们希望使用我们自己的扩展来获取某个UIView对象的width和height,我们对UIView进行扩展让其实现我们的YHSizeCompatible协议。那么该UIView就具有我们的YH类型的yh的静态变量和yh的实例变量。然后对我们的YH结构体进行扩展并使用where语句对范型Base进行类型的约束。
extension UIView: YHSizeCompatible {}
extension YH where Base: UIView {
var width: CGFloat {
return base.frame.width
}
var height: CGFloat {
return base.frame.height
}
}
4.至此我们就可以使用我们命名空间下的width和height了。下面看具体的使用例子:
let testView = UIView(frame: .init(x: 0, y: 0, width: 100, height: 200))
print("width = (testView.yh.width),height = (testView.yh.height)")
//width = 100.0,height = 200.0
在举一个例子:在比如我们可以自定义自己的随机颜色
extension UIColor: YHCompatible {}
extension YH where Base: UIColor {
static func RGBRandomColor() -> UIColor {
return UIColor(red: CGFloat(arc4random_uniform(256))/255.0, green: CGFloat(arc4random_uniform(256))/255.0, blue: CGFloat(arc4random_uniform(256))/255.0, alpha: 1.0)
}
}
我们看如何使用:
let randomColor1 = UIColor.yh.RGBRandomColor()
let randomColor2 = UIColor.yh.RGBRandomColor()
print(randomColor1)
print(randomColor2)
最近开始学习RXSwift了,看到rx中也有这样的命名空间,可见命名空间中对于swift框架和库的开发过程中的重要地位。
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base
/// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
}
}
/// A type that has reactive extensions.
public protocol ReactiveCompatible {
/// Extended type
associatedtype CompatibleType
/// Reactive extensions.
static var rx: Reactive<CompatibleType>.Type { get set }
/// Reactive extensions.
var rx: Reactive<CompatibleType> { get set }
}
extension ReactiveCompatible {
/// Reactive extensions.
public static var rx: Reactive<Self>.Type {
get {
return Reactive<Self>.self
}
set {
// this enables using Reactive to "mutate" base type
}
}
/// Reactive extensions.
public var rx: Reactive<Self> {
get {
return Reactive(self)
}
set {
// this enables using Reactive to "mutate" base object
}
}
}
import class Foundation.NSObject
/// Extend NSObject with `rx` proxy.
extension NSObject: ReactiveCompatible { }
\