Swift如何創(chuàng)建命名空間

相比于OC時(shí)代的完全沒(méi)有命名空間,Swift可以通過(guò)巧妙的辦法,實(shí)現(xiàn)幾乎等同于命名空間的效果。

需求

現(xiàn)在我們希望為UIColor類(lèi)增加一個(gè)擴(kuò)展方法,根據(jù)其自身顏色生成圖像UIImage。
在沒(méi)有命名空間的時(shí)代,可能結(jié)果是這樣子的:

let image = UIColor.blue.image

或者為避免與其它框架API同名,可能結(jié)果會(huì)變成這樣子:

let image = UIColor.blue.jx_image

當(dāng)然這種風(fēng)格非常地OC。

那有沒(méi)有優(yōu)雅一點(diǎn)的辦法來(lái)代替OC Style?比如能寫(xiě)成這樣子就好了:

let image = UIColor.blue.jx.image

Swift3繞一下路,也是可以做到的。姑且把中間的.jx叫做命名空間(Namespace),沒(méi)錯(cuò),抄了一下C#們的叫法。

定義命名空間

具體的做法通過(guò)擴(kuò)展特定的協(xié)議來(lái)達(dá)到目的。
我們需要定義兩個(gè)協(xié)議,其中一個(gè)是固定的寫(xiě)法:

/// 類(lèi)型協(xié)議
protocol TypeWrapperProtocol {
    associatedtype WrappedType
    var wrappedValue: WrappedType { get }
    init(value: WrappedType)
}

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

另一個(gè)協(xié)議基本上也是固定的寫(xiě)法,只是根據(jù)我們的需要,更改其內(nèi)的命名空間名字即可。
比如我需要一個(gè)名為jx的命名空間,就可以這樣寫(xiě):

/// 命名空間協(xié)議
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改成你希望的名字。

使用命名空間

實(shí)際上我們需要擴(kuò)展的類(lèi)不是UIColor,而是協(xié)議。
這里分兩步,第一步是讓需要擴(kuò)展的類(lèi)遵循協(xié)議NamespaceWrappable

extension UIColor: NamespaceWrappable {}

第二步是擴(kuò)展協(xié)議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
    }
}

在擴(kuò)展的方法中,self代表的是協(xié)議,而不是目標(biāo)擴(kuò)展類(lèi)。那要用到self怎么辦?用wrappedValue吧,它就是我們的目標(biāo)類(lèi)/實(shí)例。

驗(yàn)證

現(xiàn)在可以愉快地玩耍了:

let image = UIColor.blue.jx.image

使用了命名空間后,還有一個(gè)優(yōu)點(diǎn)就是可以利用Xcode的代碼補(bǔ)全。

Xcode代碼補(bǔ)全
Xcode代碼補(bǔ)全

相比在打出.im后Xcode會(huì)彈出一大堆匹配到im兩字母的方法,使用了命名空間后,點(diǎn)出.jx.時(shí),Xcode就只會(huì)提示此命名空間內(nèi)的方法/屬性。特別是StringUIView這種有巨量方法的類(lèi),只要打出命名空間就可以快速過(guò)濾不需要的方法。

下載Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容