以前在使用 Kingfisher、RxSwift 的時候,一直對 .rx 及 .kf 的實現比較疑惑,不知道其實現原理。swift
這篇文章咱們就來打造一個專屬本身的命名空間。bash
Swift 的命名空間是基於 module 而不是在代碼中顯式地指明,每一個 module 表明了 Swift 中的一個命名空間。也就是說,同一個 target 裏的類型名稱仍是不能相同的。app
// MyFramework.swift
// 這個文件存在於 MyFramework.framework 中
public class MyClass {
public class func hello() {
print("hello from framework")
}
}
// MyApp.swift
// 這個文件存在於 app 的主 target 中
class MyClass {
class func hello() {
print("hello from app")
}
}
複製代碼
在可能出現衝突的地方,咱們須要在類型名稱前面加上 module 的名字 (也就是 target 的名字):函數
// 使用哪一個 MyClass,取決因而在哪一個 target 中調用
MyClass.hello()
// hello from framework
MyFramework.MyClass.hello()
複製代碼
上面的說明雖然爲咱們解決了命名衝突的問題,可是咱們應該怎樣實現相似於 .rx、.kf 這樣本身的命名空間呢?ui
下面咱們就來一步步講解。spa
原理: 對原類型進行一層封裝。而後,對這個封裝進行自定義的方法擴展。code
如今你可能不太理解,下面咱們就一步步的來實現本身的命名空間。對象
對原類型進行一層封裝ip
// 定義泛型類
// 首先定義一個泛型類 JTKit,使用泛型 Base
public struct JTKit<Base> {
private let base: Base
public init(_ base: Base) {
self.base = base
}
}
複製代碼
定義了一個 JTWrappable 協議,這個協議表明了支持 namespace 形式的擴展。並緊接着給這個協議 extension 了默認實現。這樣實現了這個協議的類型就不須要自行實現協議所約定的內容了。ci
// 定義泛型協議
// 定義支持泛型的協議 JTWrappable,並經過協議擴展提供協議的默認實現,返回實現泛型類 JTKit 的對象自身。
public protocol JTWrappable {
associatedtype WrappableType
var jt: WrappableType { get }
}
// 協議的擴展
public extension JTWrappable {
var jt: JTKit<Self> {
get { return JTKit(self) }
}
}
複製代碼
associatedtype: 相關類型。意思也就是被associatedtype關鍵字修飾的變量,至關於一個佔位符,而不能表示具體的類型。具體的類型須要讓實現的類來指定。
須要實現命名空間的類提供 JTWrappable 協議擴展,並實現相關命名空間的對象方法(主要是擴展新的方法,如代碼中的 testMethod 方法)
extension String: JTWrappable {}
// String 命名空間 jt 中的函數
extension JTKit where Base == String {
public var testMethod: String {
return base + "namespace"
}
public func method(str: String) -> String {
return base + str
}
}
複製代碼
let str = "Hello "
print(str.jt.testMethod)
print(str.jt.method(str: "namespace"))
---輸出結果:---
Hello namespace
Hello namespace
複製代碼