用 YogaKit 實(shí)現(xiàn) Xib

前言

本文要講述的是如何使用 YogaKit 提供的 FlexBox 布局能力來(lái)實(shí)現(xiàn)類似 Xib 的功能(Xib 布局是 AutoLayout)。

GitHub 地址:https://github.com/danleechina/YogaLayout

構(gòu)想

Xib(StoryBoard) 的原理

先說(shuō)一下 Xib(StoryBoard) 的原理:

  1. 在 Xcode 中使用 Interface Builder 來(lái)構(gòu)建一個(gè)界面或者視圖榛鼎。這個(gè)過(guò)程其實(shí)就是創(chuàng)建枷踏、修改 XML 界面描述文件。右鍵 xib 類型的文件,在 Open As 中選擇 Source Code目锭,可以看到 xib 類型的文件其實(shí)就是蘋(píng)果用自己定義的一套 XML 來(lái)描述視圖
  2. 編譯的時(shí)候厌秒,IDE 會(huì)解析項(xiàng)目中所有的 xib 類型的文件,根據(jù)蘋(píng)果自己的一套規(guī)則(我們不可知)汉形,生成一個(gè)可歸檔的類纸镊,然后將該類歸檔生成一個(gè) nib 類型的二機(jī)制文件。如果項(xiàng)目中有使用 xib 的話概疆,解壓打包出來(lái)的 ipa逗威,就會(huì)看到這些 nib 類型的文件,這些文件就是 IDE 在編譯時(shí)候解析生成的岔冀。
  3. 運(yùn)行時(shí)凯旭,當(dāng)需要展示一個(gè) xib 描述的視圖時(shí),iOS 系統(tǒng)則會(huì)去加載 nib 文件得到之前編譯時(shí)候生成的歸檔類實(shí)例使套,根據(jù)這個(gè)實(shí)例生成視圖需要的所有子視圖罐呼,并設(shè)置這些子視圖的約束和屬性
  4. 最后如果有設(shè)置 IBOutlet 的話,會(huì)將生成的視圖賦值給其 owner侦高。

想要了解 xib 更加深入的內(nèi)容可以查看我之前翻譯的一篇文章:macOS 和 iOS 中 Nib 文件實(shí)現(xiàn)原理以及最佳實(shí)踐

可以看到嫉柴,要實(shí)現(xiàn)類似 Xib 這樣的工具需要如下一些條件:

  1. 一套類似的 XML 來(lái)描述視圖的組成(比如某個(gè)視圖有哪些子視圖,它又是那個(gè)視圖的子視圖)奉呛,配置視圖的屬性(比如配置 label 的 text 屬性)计螺,以及定義視圖之間的布局(比如使用 autolayout)
  2. 出于性能考慮,可以提前解析該 XML瞧壮,生成類似 nib 的類
  3. 運(yùn)行時(shí)解析該 XML(如果在編譯階段提前解析了登馒,則不需要),將 XML 中視圖的組成咆槽,視圖的屬性陈轿,視圖的布局給提取出來(lái),動(dòng)態(tài)生成相應(yīng)視圖,并配置其屬性济欢、子視圖赠堵、父視圖、布局等
  4. 如果 XML 描述的文件有指定的 Outlet 的話法褥,則將其賦值給相應(yīng)的類

構(gòu)想實(shí)現(xiàn)

定義 XML 描述視圖規(guī)則

<UIView id="gradeTipView" style="alignItems:center;justifyContent:center; marginLeft:12;marginRight:8">
    <UILabel id="gradeNameLabel" style=""></UILabel>
    <StarBarView id="starBarView" style=""></StarBarView>
</UIView>
  1. 在這里茫叭,每一個(gè) XML 標(biāo)簽名字是視圖類的名字,以便運(yùn)行時(shí)通過(guò) NSClassFromString 得到類對(duì)象半等,再通過(guò)類對(duì)象生成該視圖類的一個(gè)實(shí)例
  2. 每一個(gè) XML 標(biāo)簽有一些屬性揍愁,比如上面的 id 和 style。id 的作用等同于 IBOutlet杀饵,將動(dòng)態(tài)生成的類實(shí)例賦值給其 owner莽囤,style 的作用是描述布局,然后將其設(shè)置到 YogaKit 中切距。還可以添加別的屬性朽缎,比如說(shuō)如果是 UILabel 的話設(shè)置 text="我是文本" 來(lái)描述其 text 屬性,代碼中使用 KVC 來(lái)實(shí)現(xiàn)
  3. style 屬性的值指定多個(gè)的時(shí)候需要通過(guò)分號(hào)隔離谜悟,鍵值對(duì)通過(guò)冒號(hào)隔離
  4. 每一個(gè) XML 標(biāo)簽會(huì)包含其他 XML 標(biāo)簽话肖,比如上面 UIView 包含一個(gè) UILabel 標(biāo)簽,一個(gè)自定義的 StarBarView 標(biāo)簽葡幸,意思就是說(shuō)該 UIView 有兩個(gè)子視圖最筒,第一個(gè)是一個(gè) UILabel,第二個(gè)是自定義視圖 StarBarView
  5. 為了簡(jiǎn)單蔚叨,每一個(gè)類似該 XML 的文件只能有一個(gè)根標(biāo)簽

比如不能出現(xiàn)下列場(chǎng)景:

<UIView></UIView>
<UILabel></UILabel>
<UIButton></UIButton>

在這里床蜘,根標(biāo)簽有三個(gè),第一個(gè) UIView蔑水,第二個(gè) UILabel邢锯,第三個(gè) UIButton,這個(gè)情況目前不被允許(對(duì) xib 了解的可能會(huì)知道從 nib 獲取視圖對(duì)象會(huì)返回一個(gè)數(shù)組搀别,就是說(shuō) xib 可以有多個(gè)根層級(jí)的視圖)

實(shí)現(xiàn)細(xì)節(jié)

  1. 如何解析 XML丹擎?為了簡(jiǎn)單起見(jiàn)我直接使用了蘋(píng)果官方處理 XML 的類 NSXMLParser。實(shí)現(xiàn)代理方法领曼,調(diào)用 parse 函數(shù)即可完成 XML 解析。有一點(diǎn)要注意蛮穿,調(diào)用 parse 函數(shù)是同步的庶骄,也就是說(shuō)當(dāng) parse 函數(shù)返回時(shí),如果實(shí)現(xiàn)了代理方法践磅,則代理方法均已經(jīng)被使用過(guò)了单刁。
  2. 解析 XML 的結(jié)果是一個(gè)樹(shù)形的數(shù)據(jù)模型,該樹(shù)形結(jié)構(gòu)的每一個(gè)節(jié)點(diǎn)包含視圖類的名字,視圖的屬性(包括視圖的布局信息)羔飞,子視圖信息肺樟,以及父視圖信息(沒(méi)有父視圖意味則是根節(jié)點(diǎn))
  3. 從樹(shù)形數(shù)據(jù)模型的根節(jié)點(diǎn)開(kāi)始動(dòng)態(tài)生成該視圖的實(shí)例,并配置實(shí)例的屬性逻淌,子視圖信息和父視圖信息等
  4. 在 XML 中有時(shí)候定義一個(gè)視圖的寬高時(shí)會(huì)需要屏幕寬高的信息么伯,并做一下簡(jiǎn)單表達(dá)式的計(jì)算,比如視圖的高時(shí)屏幕的高的 2/3卡儒,這里做表達(dá)式計(jì)算的時(shí)候可以使用 NSExpression 來(lái)處理田柔。
  5. 用 Swift 編寫(xiě)的視圖類使用 Objective C 來(lái)動(dòng)態(tài)生成的時(shí)候,需要加上當(dāng)前二機(jī)制文件的名字骨望,這個(gè)需要注意

未來(lái)

  1. 支持動(dòng)態(tài)設(shè)置文本硬爆、顏色、圖片擎鸠、CGRect(結(jié)構(gòu)體) 等屬性
  2. 簡(jiǎn)化 Swift 中 Outlet 的設(shè)置
  3. 考慮能否去掉 Outlet缀磕,使用者傳入數(shù)據(jù),數(shù)據(jù)和視圖能夠雙向綁定
  4. 支持 Debug 模式下不重新編譯劣光,僅需更改 XML 文件即可更新視圖布局

參考

  1. XML 教程
  2. Flex 布局教程:語(yǔ)法篇
  3. Yoga Kit
  4. macOS 和 iOS 中 Nib 文件實(shí)現(xiàn)原理以及最佳實(shí)踐
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末袜蚕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子赎线,更是在濱河造成了極大的恐慌廷没,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垂寥,死亡現(xiàn)場(chǎng)離奇詭異颠黎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)滞项,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)狭归,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人文判,你說(shuō)我怎么就攤上這事过椎。” “怎么了戏仓?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵疚宇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我赏殃,道長(zhǎng)敷待,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任仁热,我火速辦了婚禮榜揖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己举哟,他們只是感情好思劳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著妨猩,像睡著了一般潜叛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上册赛,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天钠导,我揣著相機(jī)與錄音,去河邊找鬼森瘪。 笑死牡属,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的扼睬。 我是一名探鬼主播逮栅,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼窗宇!你這毒婦竟也來(lái)了措伐?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤军俊,失蹤者是張志新(化名)和其女友劉穎侥加,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體粪躬,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡担败,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镰官。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片提前。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泳唠,靈堂內(nèi)的尸體忽然破棺而出狈网,到底是詐尸還是另有隱情,我是刑警寧澤笨腥,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布拓哺,位于F島的核電站,受9級(jí)特大地震影響脖母,放射性物質(zhì)發(fā)生泄漏士鸥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一镶奉、第九天 我趴在偏房一處隱蔽的房頂上張望础淤。 院中可真熱鬧,春花似錦哨苛、人聲如沸鸽凶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)玻侥。三九已至,卻和暖如春亿蒸,著一層夾襖步出監(jiān)牢的瞬間凑兰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工边锁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姑食,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓茅坛,卻偏偏與公主長(zhǎng)得像音半,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贡蓖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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

  • 1曹鸠、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_x閱讀 15,968評(píng)論 3 119
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,321評(píng)論 8 265
  • 做一道選擇題彻桃,如果讓你選一個(gè)人相伴一生,你希望這個(gè)人是愛(ài)你的晾蜘,還是你愛(ài)的邻眷?前提是不能兩全。 這是一個(gè)爛大街的無(wú)聊問(wèn)...
    石頭姑娘的藏書(shū)館閱讀 2,483評(píng)論 0 1
  • 多殘忍笙纤,你和我耗溜,就像流星劃過(guò) 有些話,說(shuō)出去就不能收回省容, 看到了抖拴,就是傷人于無(wú)形, 所以腥椒,我不再輕易說(shuō)出口了. 現(xiàn)...
    青春釋殘了悲閱讀 240評(píng)論 0 0