R.Swift - iOS高效資源引用框架探究

前言

Android中的資源引用 & "R"

在接觸iOS開(kāi)發(fā)之前,我也曾搞過(guò)一段時(shí)間的Android開(kāi)發(fā)姿染。在Android開(kāi)發(fā)中赋咽,其對(duì)于資源的引用非常方便,我們可以通過(guò)"R機(jī)制"來(lái)對(duì)Android中的圖片(Drawable)菌湃、布局(Layout)、動(dòng)畫(huà)配置(Anim)遍略、國(guó)際化字符串(String)惧所、尺寸(Dimen)等等資源進(jìn)行非常方便快捷的引用骤坐。什么是R機(jī)制?在我們創(chuàng)建一個(gè)Android項(xiàng)目的時(shí)候下愈,IDE會(huì)自動(dòng)幫我們創(chuàng)建一個(gè)名為R的類型纽绍,它所在的文件名稱也是叫做R.javaR類型中沒(méi)有任何方法势似,包含的是代表不同類型資源的內(nèi)部靜態(tài)類拌夏,而這些內(nèi)部靜態(tài)類中,也只有靜態(tài)的屬性履因,每個(gè)屬性代表一個(gè)資源障簿,故我們要引用某個(gè)資源類型中的某個(gè)資源,可用R.資源類型.資源名來(lái)引用搓逾。下面就是代碼中的實(shí)例:

//  在Activity中設(shè)置其自己的視圖布局
RootActivity.this.setContentView(R.layout.activity_root);

//  從圖片資源文件夾中加載名為"image_test"的圖片以其創(chuàng)建位圖
Bitmap aBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.image_test);

//  以id為基準(zhǔn)找到某個(gè)視圖控件
this.showTextView = (TextView)this.findViewById(R.id.show_text_view);

巧妙的是卷谈,我們無(wú)需對(duì)R類進(jìn)行任何的修改或定義杯拐,IDE會(huì)幫我們自動(dòng)完成:當(dāng)我們把一張圖片復(fù)制入drawable文件夾中霞篡,R類的drawable內(nèi)部類會(huì)自動(dòng)聲明并定義了一個(gè)名字與圖片相同的靜態(tài)屬性,屬性的類型為int端逼,用于對(duì)資源的唯一標(biāo)識(shí)朗兵,同樣的,當(dāng)我們創(chuàng)建一個(gè)layout布局文件顶滩,或者在定義color余掖、dimensstringxml配置文件中新增新配置資源礁鲁,IDE都會(huì)根據(jù)資源的改變自動(dòng)配置R類盐欺。

iOS中的資源引用

當(dāng)我從Android轉(zhuǎn)至iOS后,我瞬間覺(jué)得iOS的資源引用略為惡心仅醇,跟Android比起來(lái)冗美,它更加蛋疼麻煩,舉幾個(gè)例子:

  1. 我現(xiàn)在Assets圖片庫(kù)中有一張圖片析二,名為image_test粉洼,好,我現(xiàn)在要?jiǎng)?chuàng)建一個(gè)UIImage對(duì)象叶摄,讓其解碼這張圖片属韧。代碼是這樣子的:
let aImage = UIImage(named: "image_test")

在這里,我使用的UIImage構(gòu)造方法需要傳入一個(gè)字符串參數(shù)蛤吓,這個(gè)字符串要求為圖片的名字宵喂。在調(diào)用這個(gè)構(gòu)造方法的時(shí)候,我的心里有股蛋蛋的憂傷... what? 我要自己輸入一個(gè)字符串会傲,才能構(gòu)造出這個(gè)實(shí)例樊破?就算我不手打愉棱,直接復(fù)制圖片名字也好,我還要跳到Finder或者Assets中“Command + C”再回到代碼區(qū)中“Command + V”哲戚,不僅如此奔滑,UIImage(named:)構(gòu)造方法所返回的類型是Optional類型,原因是我在輸入圖片名字構(gòu)造的時(shí)候可能誤將名字打錯(cuò)了顺少,又或者圖片在之前不小心被我刪除了朋其,Swift不能保證構(gòu)造出的UIImage一定非空... 略坑??

  1. 很多時(shí)候,我們會(huì)用到Nib來(lái)自定義一個(gè)視圖脆炎,比如UITableViewCell梅猿;當(dāng)我們?cè)?code>Nib中布局配置好視圖后,我們就需要在代碼區(qū)中引用它秒裕,下面就是UITableView注冊(cè)一個(gè)以Nib構(gòu)建的Cell的例子:
let tableView = UITableView(frame: CGRectZero, style: .Plain)
tableView.registerNib(UINib(nibName: "TanTableViewCell", bundle: nil), forCellReuseIdentifier: ViewController.CELL_IDENTIFIER)

首先我在之前已經(jīng)創(chuàng)建好了一個(gè)名為TanTableViewCellNib袱蚓,然后我們?cè)跒閁ITableViewC注冊(cè)Cell的時(shí)候,則需要以我們創(chuàng)建的Cell的Nib文件名字符串為參數(shù)傳入UINib的構(gòu)造方法中几蜻。這里的問(wèn)題跟上面所說(shuō)的創(chuàng)建UIImage一樣喇潘,使用字符串作為參數(shù)構(gòu)建某些資源實(shí)例時(shí),效率會(huì)較為低下梭稚,并且由于輸入的錯(cuò)誤颖低,最終或許會(huì)導(dǎo)致實(shí)例無(wú)法構(gòu)建,這是iOS開(kāi)發(fā)API中一處蛋疼的地方弧烤。

R.Swift? 什么東東忱屑?

根據(jù)前言中關(guān)于Android資源引用的內(nèi)容,顧名思義暇昂,R.Swift是一款基于Swift平臺(tái)莺戒,針對(duì)iOS以及TVOS開(kāi)發(fā)的仿Android資源引用框架。它所針對(duì)的問(wèn)題急波,就是類似于剛剛我在上方提到的一樣从铲,避免使用字符串來(lái)構(gòu)造某些資源實(shí)例。R.Swift能夠在我們修改項(xiàng)目資源后動(dòng)態(tài)地進(jìn)行配置幔崖,最終食店,你能夠使用類似語(yǔ)法R.資源類型.資源名稱來(lái)對(duì)某資源進(jìn)行引用構(gòu)建。R.Swift有著動(dòng)態(tài)生成代碼的機(jī)制赏寇,由此吉嫩,它具有以下極具魅力的優(yōu)點(diǎn):

  • 代碼自動(dòng)補(bǔ)全 :就像輸入其他的代碼一樣,R.Swift支持IDE的代碼自動(dòng)補(bǔ)全嗅定,當(dāng)你的資源量非常龐大時(shí)自娩,你只需把資源調(diào)用語(yǔ)法的前沿部分敲出來(lái),IDE就會(huì)自動(dòng)給予代碼提示以及補(bǔ)全,這對(duì)資源的引用效率有著顯著的提高忙迁。
  • 自動(dòng)檢測(cè) : 當(dāng)我們寫(xiě)入某些錯(cuò)誤的代碼時(shí)脐彩,IDE會(huì)向我們反饋錯(cuò)誤以及警告,如我們調(diào)用某個(gè)類中不存在的方法時(shí)姊扔,IDE就會(huì)立即檢測(cè)出代碼的錯(cuò)誤惠奸,并給予反饋。在R.Swift中恰梢,若我們將資源重命名佛南,或干脆將資源刪除了,R.Swift會(huì)自動(dòng)重新進(jìn)行配置嵌言,而在之前我們對(duì)該資源進(jìn)行引用的地方嗅回,IDE也會(huì)相應(yīng)的向我們報(bào)錯(cuò),表明資源的不存在摧茴,如此一來(lái)绵载,我們就不必?fù)?dān)心資源的修改刪除對(duì)代碼的蝴蝶效應(yīng)了。

總之一句話苛白,R.Swift猴犀利娃豹!

R.Swift的安裝配置

在這里我們使用的是CocoaPods來(lái)對(duì)R.Swift進(jìn)行安裝,相關(guān)的步驟也不必累贅說(shuō)明丸氛,一句pod install后我們把R.Swift安裝進(jìn)來(lái)了培愁。下面要進(jìn)行R.Swift的配置著摔,主要有幾個(gè)步驟:

  1. 進(jìn)入項(xiàng)目的配置界面缓窜,在左邊的TARGETS項(xiàng)下面選擇我們的項(xiàng)目,并在右邊點(diǎn)擊Build Phases這個(gè)tab谍咆。
  2. 進(jìn)入Build Phases這個(gè)tab后禾锤,我們看到左上角有一個(gè)"+"按鈕,點(diǎn)擊并在彈出的選項(xiàng)卡中選擇New Run Script Phase摹察。
  3. 我們會(huì)看到界面的下方多出了一個(gè)Run Script項(xiàng)恩掷,展開(kāi)它,并在腳本輸入?yún)^(qū)域輸入"$PODS_ROOT/R.swift/rswift" "$SRCROOT" (第二對(duì)雙引號(hào)括起來(lái)所代碼的是項(xiàng)目的根目錄供嚎,你也可以放到根目錄下的其他目錄中黄娘,只需將其修改為"$SRCROOT/XXX",XXX為目標(biāo)目錄名)克滴。
  4. 我們按住新建的這個(gè)Run Script項(xiàng)向上移動(dòng)逼争,移到Compile Source項(xiàng)的上方,不過(guò)也要保證此時(shí)它也在Check Pods Manifest.lock項(xiàng)的下方劝赔。
  5. Command + B誓焦,編譯一下,編譯成功后着帽,在Finder進(jìn)入到剛剛我們制定的目錄中杂伟,此時(shí)我們會(huì)看到一個(gè)名為R.generated.swift的文件已經(jīng)創(chuàng)建了移层,直接把此文件拖入Xcode項(xiàng)目中,記住不要勾選Copy items if needed項(xiàng)赫粥。
  6. 配置到此完成观话,我們可以構(gòu)建自己的項(xiàng)目了

R.Swift對(duì)資源修改并編譯后都會(huì)在R.generated.swift文件中自動(dòng)生成代碼,我們也可以打開(kāi)這個(gè)文件看一下現(xiàn)在資源的構(gòu)造情況越平,這里只截了一小段代碼展示:

  /// This `R.font` struct is generated, and contains static references to 0 fonts.
  struct font {
    private init() {}
  }
  
  /// This `R.image` struct is generated, and contains static references to 1 images.
  struct image {
    /// Image `kafei`.
    static let kafei = ImageResource(bundle: _R.hostingBundle, name: "kafei")
    
    /// `UIImage(named: "kafei", bundle: ..., traitCollection: ...)`
    static func kafei(compatibleWithTraitCollection traitCollection: UITraitCollection? = nil) -> UIImage? {
      return UIImage(resource: R.image.kafei, compatibleWithTraitCollection: traitCollection)
    }
    
    private init() {}
  }
  
  /// This `R.nib` struct is generated, and contains static references to 1 nibs.
  struct nib {
    /// Nib `TanTableViewCell`.
    static let tanTableViewCell = _R.nib._TanTableViewCell()
    
    /// `UINib(name: "TanTableViewCell", bundle: ...)`
    static func tanTableViewCell(_: Void) -> UINib {
      return UINib(resource: R.nib.tanTableViewCell)
    }
    
    private init() {}
  }

R.Swift的使用

在這里要說(shuō)明一下匪燕,每當(dāng)我們修改了資源,我們需要Command + B來(lái)編譯一下項(xiàng)目從而讓R.Swift自動(dòng)進(jìn)行配置更新喧笔。


下面就來(lái)用實(shí)例演示一下R.Swift的使用帽驯,并與原生的API進(jìn)行比對(duì):

Image - 圖片

//  不使用R.Swift
let pImage = UIImage(named: "image_test")
//  使用R.Swift
let nImage = R.image.image_test()

File - 數(shù)據(jù)文件

//  不使用R.Swift
let pFile = NSBundle.mainBundle().pathForResource("DataFile", ofType: "json")
//  使用R.Swift
let nFile = R.file.dataFileJson.path()

Font - 字體

//  不使用R.Swift
let pFont = UIFont(name: "chalkduster", size: 35)
//  使用R.Swift
let nFont = R.font.chalkduster(size: 35)
//  你看,非常神奇书闸,在上面的方法中你不僅可以選擇字體類型尼变,還能設(shè)置字體大小

Color - 顏色

顏色這里我覺(jué)得有必要細(xì)講一下,一個(gè)較為龐大的項(xiàng)目浆劲,其顏色資源配置也是相應(yīng)比較復(fù)雜嫌术,如某些視圖的背景顏色、字體的顏色等等牌借,以往我們進(jìn)行顏色資源的配置度气,一般會(huì)定義一個(gè)全局的Config文件或類,里面就存有各種顏色膨报,每種顏色用有意義的名稱去標(biāo)識(shí)磷籍。R.Swift與其不同的是,它還能有更贊的方式導(dǎo)入顏色資源:

Color Palette

呵呵现柠,這個(gè)方式可以說(shuō)是非常的花式院领,配合R.Swift使用起來(lái)簡(jiǎn)直6得飛起!
當(dāng)我們?cè)诳梢暬晥D編輯界面(如Storyboard)中為一個(gè)視圖配置某些顏色時(shí)够吩,我們可以進(jìn)入顏色調(diào)色板來(lái)選擇更多的顏色比然,如圖:

調(diào)色板

在其中,我們可以創(chuàng)建自己的調(diào)色板周循,如現(xiàn)在我創(chuàng)建了一個(gè)名為MyAppColor的調(diào)色板:
自定義調(diào)色板

這個(gè)自定義的調(diào)色板是不局限于現(xiàn)在的項(xiàng)目强法,以后我們創(chuàng)建的每一個(gè)項(xiàng)目都可以使用這個(gè)調(diào)色板。如果你的UI設(shè)計(jì)師夠醒目的話湾笛,他也可以給我們提供一個(gè)設(shè)計(jì)師調(diào)好顏色的調(diào)色板饮怯,現(xiàn)在問(wèn)題來(lái)了,設(shè)計(jì)師在他的電腦里定義好了調(diào)色板迄本,怎么share出去呢硕淑?其實(shí)我們每自定義一個(gè)調(diào)色板,它都會(huì)以二進(jìn)制文件的形式儲(chǔ)存在電腦中,位置在~/Library/Colors/(隱藏文件目錄置媳,要訪問(wèn)它要不取消Finder隱藏于樟,要不直接控制臺(tái)open跳進(jìn)來(lái)),文件的名字為調(diào)色板名.clr拇囊,把它直接copy下來(lái)就行迂曲。
R.Swift能夠非常花式地使用調(diào)色板寥袭,有多花式路捧?
就現(xiàn)在來(lái)說(shuō),我直接把我創(chuàng)建的調(diào)色板的文件MyAppColor.clr拖進(jìn)項(xiàng)目中传黄,Command + B編譯下杰扫,然后,我現(xiàn)在可以這樣子得到顏色了:

let appRedColor = R.color.myAppColor.red()

簡(jiǎn)直6到飛起膘掰!??

Nib

//  不使用R.Swift
tableView.registerNib(UINib(nibName: "TanTableViewCell", bundle: nil), forCellReuseIdentifier: CELL_IDENTIFIER)
//  使用R.Swift
tableView.registerNib(R.nib.tanTableViewCell(), forCellReuseIdentifier: CELL_IDENTIFIER)

UITableView中的復(fù)用

上面的代碼讓TableView注冊(cè)了其cell所屬的Nib章姓,并輸入了cell的復(fù)用標(biāo)識(shí)符,而在另一種情況下识埋,比如我們?cè)谠O(shè)計(jì)cell的Nib時(shí)已經(jīng)在Nib中設(shè)置好了cell的復(fù)用標(biāo)識(shí)符凡伊,我們就沒(méi)必要在TableView注冊(cè)cell的時(shí)候再配置一遍了,幸虧,R.Swift給我們提供了高效率的cell注冊(cè)以及復(fù)用方法:

  1. 首先在Cell的Nib中設(shè)置好復(fù)用標(biāo)識(shí)符(Identifier)
  2. 進(jìn)行Cell的注冊(cè)
tableView.registerNib(R.nib.tanTableViewCell)
  1. 編寫(xiě)TableView數(shù)據(jù)源的Cell返回方法
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(R.nib.tanTableViewCell.identifier, forIndexPath: indexPath)
    //  Do Something
    return cell
}

R.Swift也支持對(duì)UICollectionView中Cell的高效注冊(cè)與復(fù)用窒舟,方式跟UITableView也是差不多系忙,在這里就不累贅說(shuō)明了。


以上說(shuō)明了使用R.Swift進(jìn)行各種資源的引用構(gòu)造惠豺,除了上面的資源外银还,R.Swift還能作用于Localized string(本地化字符串)Storyboards耕腾、Segues這些資源见剩,其大大提高了iOS開(kāi)發(fā)的資源引用構(gòu)造效率杀糯。

運(yùn)行時(shí)檢測(cè)

R.Swift提供運(yùn)行時(shí)檢測(cè)功能扫俺,在項(xiàng)目運(yùn)行的時(shí)候能夠檢測(cè)其生成的代碼是否和此時(shí)項(xiàng)目的資源完全匹配,調(diào)用的是R.assertValid()固翰,這個(gè)方法在release模式下是不做任何操作的狼纬,它只作用于debug(調(diào)試)模式,檢測(cè)的內(nèi)容為:

  • 是否所有在Storyboard中使用的圖片都可用骂际。
  • 是否所有定義在Storyboard中疗琉,且需要用標(biāo)識(shí)符去加載的視圖控制器都能夠成功加載。
    官方建議把這個(gè)檢測(cè)方法放到項(xiàng)目的AppDelegate中歉铝。

相關(guān)鏈接

R.Swift的Github地址

Github - R.Swift

參考資料

R.Swift官方說(shuō)明文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盈简,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柠贤,老刑警劉巖香浩,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異臼勉,居然都是意外死亡邻吭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)宴霸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)囱晴,“玉大人,你說(shuō)我怎么就攤上這事瓢谢』矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵氓扛,是天一觀的道長(zhǎng)艺糜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)幢尚,這世上最難降的妖魔是什么破停? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮尉剩,結(jié)果婚禮上真慢,老公的妹妹穿的比我還像新娘。我一直安慰自己理茎,他們只是感情好黑界,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著皂林,像睡著了一般朗鸠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上础倍,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天烛占,我揣著相機(jī)與錄音,去河邊找鬼沟启。 笑死忆家,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的德迹。 我是一名探鬼主播芽卿,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼胳搞!你這毒婦竟也來(lái)了卸例?” 一聲冷哼從身側(cè)響起称杨,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎筷转,沒(méi)想到半個(gè)月后列另,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旦装,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年页衙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阴绢。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡店乐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呻袭,到底是詐尸還是另有隱情眨八,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布左电,位于F島的核電站廉侧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏篓足。R本人自食惡果不足惜段誊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望栈拖。 院中可真熱鬧连舍,春花似錦、人聲如沸涩哟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贴彼。三九已至潜腻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間器仗,已是汗流浹背融涣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留青灼,地道東北人暴心。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杂拨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悯衬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 UI下拉刷新模糊效果A...
    袁俊亮技術(shù)博客閱讀 11,925評(píng)論 9 105
  • 嗯哼嗯哼蹦擦擦~~~ 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 ...
    philiha閱讀 4,881評(píng)論 0 6
  • 你買(mǎi)了件好衣服弹沽,買(mǎi)了雙好鞋檀夹,卻總等著“大日子”才穿,最后衣服舊了策橘,鞋子過(guò)時(shí)了炸渡。我不明白你為什么只有在特定的日子才想...
    微塵九回閱讀 257評(píng)論 0 0