Swift-命名空間,反射機(jī)制

6d66c5b41af24014b0617b5e16a9fdbb.png

傳送門
Objective-C 一個(gè)一直以來令人詬病的地方就是沒有命名空間,在應(yīng)用開發(fā)時(shí),所有的代碼和引用的靜態(tài)庫最終都會(huì)被編譯到同一個(gè)域和二進(jìn)制中。這樣的后果是一旦我們有重復(fù)的類名的話,就會(huì)導(dǎo)致編譯時(shí)的沖突和失敗。為了避免這種事情的發(fā)生,Objective-C 的類型一般都會(huì)加上兩到三個(gè)字母的前綴,比如 Apple 保留的 NS 和 UI 前綴,各個(gè)系統(tǒng)框架的前綴 SK (StoreKit),CG (CoreGraphic) 等。Objective-C 社區(qū)的大部分開發(fā)者也遵守了這個(gè)約定,一般都會(huì)將自己名字縮寫作為前綴,把類庫命名為 AFNetworking 或者 MBProgressHUD 這樣。這種做法可以解決部分問題,至少我們?cè)谥苯右貌煌说膸鞎r(shí)沖突的概率大大降低了,但是前綴并不意味著不會(huì)沖突,有時(shí)候我們確實(shí)還是會(huì)遇到即使使用前綴也仍然相同的情況。另外一種情況是可能你想使用的兩個(gè)不同的庫,分別在它們里面引用了另一個(gè)相同的很流行的第三方庫,而又沒有更改名字。在你分別使用這兩個(gè)庫中的一個(gè)時(shí)是沒有問題的,但是一旦你將這兩個(gè)庫同時(shí)加到你的項(xiàng)目中的話,這個(gè)大家共用的第三方庫就會(huì)和自己發(fā)生沖突了。

在 Swift 中,由于可以使用命名空間了,即使是名字相同的類型,只要是來自不同的命名空間的話,都是可以和平共處的。和 C# 這樣的顯式在文件中指定命名空間的做法不同,Swift 的命名空間是基于 module 而不是在代碼中顯式地指明,每個(gè) module 代表了 Swift 中的一個(gè)命名空間。也就是說,同一個(gè) target 里的類型名稱還是不能相同的。在我們進(jìn)行 app 開發(fā)時(shí),默認(rèn)添加到 app 的主 target 的內(nèi)容都是處于同一個(gè)命名空間中的,我們可以通過創(chuàng)建 Cocoa (Touch) Framework 的 target 的方法來新建一個(gè) module,這樣我們就可以在兩個(gè)不同的 target 中添加同樣名字的類型了:

  • 在swift 中存在命名空間,同一命名空間下全局共享.
  • 第三方框架使用:直接拖入項(xiàng)目中,從屬于一個(gè)命名空間,很可能沖突(所以盡量用cocoapod)
  • NSClassFromString(反射機(jī)制): 最重要的目的,就是解耦 。例子:(反射機(jī)制和工廠方法)
// MyFramework.swift
// 這個(gè)文件存在于 MyFramework.framework 中
public class MyClass {
    public class func hello() {
        print("hello from framework")
    }
}

// MyApp.swift
// 這個(gè)文件存在于 app 的主 target 中
class MyClass {
    class func hello() {
        print("hello from app")
    }
}

在使用時(shí),如果出現(xiàn)可能沖突的時(shí)候,我們需要在類型名稱前面加上 module 的名字 (也就是 target 的名字):

MyClass.hello()
// hello from app

MyFramework.MyClass.hello()
// hello from framework

因?yàn)槭窃?app 的 target 中調(diào)用的,所以第一個(gè) MyClass 會(huì)直接使用 app 中的版本,第二個(gè)調(diào)用我們指定了 MyFramework 中的版本。

另一種策略是使用類型嵌套的方法來指定訪問的范圍。常見做法是將名字重復(fù)的類型定義到不同的 struct 中,以此避免沖突。這樣在不使用多個(gè) module 的情況下也能取得隔離同樣名字的類型的效果:

struct MyClassContainer1 {
    class MyClass {
        class func hello() {
            print("hello from MyClassContainer1")
        }
    }
}

struct MyClassContainer2 {
    class MyClass {
        class func hello() {
            print("hello from MyClassContainer2")
        }
    }
}

使用時(shí):

MyClassContainer1.MyClass.hello()
MyClassContainer2.MyClass.hello()

其實(shí)不管哪種方式都和傳統(tǒng)意義上的命名空間有所不同,把它叫做命名空間,更多的是一種概念上的宣傳。不過在實(shí)際使用中只要遵守這套規(guī)則的話,還是能避免很多不必要的麻煩的,至少唾手可得的是我們不再需要給類名加上各種奇怪的前綴了。

實(shí)戰(zhàn):通過字符串獲取 類

在 AppDelegate 中設(shè)置window 的根控制器

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow()
        window?.backgroundColor = UIColor.white
        // 設(shè)置根控制器,需要添加命名空間 -》 通常是 "項(xiàng)目名.ClassName"
        // 注意: 項(xiàng)目名 不能有 數(shù)字 特殊符號(hào)
        // (1) 獲取命名空間
        let nameSpace = Bundle.main.infoDictionary?["CFBundleName"] as! String
        //(2) 拼接
        let clsName = nameSpace + "." + "ViewController"
        //AnyClass? ->視圖控制器的類型
        let cls = NSClassFromString(clsName) as? UIViewController.Type
        // 使用類名創(chuàng)建 控制器
        let vc = cls?.init()
        window?.rootViewController = vc
        window?.makeKeyAndVisible()
        return true
    }
最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Objective-C 一個(gè)一直以來令人詬病的地方就是沒有命名空間,在應(yīng)用開發(fā)時(shí),所有的代碼和引用的靜態(tài)庫最終都會(huì)...
    二先生Developer閱讀 1,204評(píng)論 0 1
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,922評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,177評(píng)論 4 61
  • 臨近期末,每天都很忙,我每天都想早睡早起,可堅(jiān)持不了一天,便會(huì)回到原樣,因此可見,一個(gè)人的習(xí)慣,想要輕易改變,真不...
    06暖陽閱讀 424評(píng)論 2 2
  • 起初,神創(chuàng)造天地。地是空虛混沌,淵面黑暗;神的靈運(yùn)行在水面上。 神說:“要有光”,就有了光。神看光是好的,就把光暗...
    OnlywantyouJesu閱讀 521評(píng)論 0 0

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