https://github.com/jiongxing/namespacedemo
Swift Namespace, Swift创建命名空间
https://github.com/jiongxing/namespacedemo
namespace swift
Last synced: 3 months ago
JSON representation
Swift Namespace, Swift创建命名空间
- Host: GitHub
- URL: https://github.com/jiongxing/namespacedemo
- Owner: JiongXing
- Created: 2017-05-09T11:09:50.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2017-05-09T12:18:10.000Z (about 9 years ago)
- Last Synced: 2025-04-01T01:01:47.639Z (about 1 year ago)
- Topics: namespace, swift
- Language: Swift
- Homepage: http://www.jianshu.com/p/527ca32ef380
- Size: 10.7 KB
- Stars: 4
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
> 相比于OC时代的完全没有命名空间,Swift可以通过巧妙的办法,实现几乎等同于命名空间的效果。
# 需求
现在我们希望为`UIColor`类增加一个扩展方法,根据其自身颜色生成图像`UIImage`。
在没有命名空间的时代,可能结果是这样子的:
```swift
let image = UIColor.blue.image
```
或者为避免与其它框架API同名,可能结果会变成这样子:
```swift
let image = UIColor.blue.jx_image
```
当然这种风格非常地OC。
那有没有优雅一点的办法来代替OC Style?比如能写成这样子就好了:
```swift
let image = UIColor.blue.jx.image
```
Swift3绕一下路,也是可以做到的。姑且把中间的`.jx`叫做命名空间(Namespace),没错,抄了一下C#们的叫法。
# 定义命名空间
具体的做法通过扩展特定的协议来达到目的。
我们需要定义两个协议,其中一个是固定的写法:
```swift
/// 类型协议
protocol TypeWrapperProtocol {
associatedtype WrappedType
var wrappedValue: WrappedType { get }
init(value: WrappedType)
}
struct NamespaceWrapper: TypeWrapperProtocol {
let wrappedValue: T
init(value: T) {
self.wrappedValue = value
}
}
```
另一个协议基本上也是固定的写法,只是根据我们的需要,更改其内的命名空间名字即可。
比如我需要一个名为`jx`的命名空间,就可以这样写:
```swift
/// 命名空间协议
protocol NamespaceWrappable {
associatedtype WrapperType
var jx: WrapperType { get }
static var jx: WrapperType.Type { get }
}
extension NamespaceWrappable {
var jx: NamespaceWrapper {
return NamespaceWrapper(value: self)
}
static var jx: NamespaceWrapper.Type {
return NamespaceWrapper.self
}
}
```
需要什么样的命名空间,就把其中的`jx`改成你希望的名字。
# 使用命名空间
实际上我们需要扩展的类不是`UIColor`,而是协议。
这里分两步,第一步是让需要扩展的类遵循协议`NamespaceWrappable`:
```swift
extension UIColor: NamespaceWrappable {}
```
第二步是扩展协议`TypeWrapperProtocol`:
```swift
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`吧,它就是我们的目标类/实例。
# 验证
现在可以愉快地玩耍了:
```swift
let image = UIColor.blue.jx.image
```
使用了命名空间后,还有一个优点就是可以利用Xcode的代码补全。

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