Storyboard 與 Xib 的“抉擇”

同步:ckitakishi.com

近期開始進行一個新項目的原型制作及其結(jié)構(gòu)設(shè)計拘鞋,打算把一些心路歷程記錄下來,隨便先給它取個名字叫做:P-OOP灰蛙。

比起手寫 UI傅事,“拖控件”的 Storyboard 和 Xib 似乎一直都更投我所好。不過即使是 Storyboard 和 Xib 之間蹭越,似乎也還是多多少少有一些紛爭响鹃。

Storyboard & Xib

公司 (年久失修) 的 iOS Guidelines 中寫著一句話:

進行源碼管理時 Storyboard 極易導(dǎo)致沖突案训,團隊開發(fā)時,各畫面與各組件盡可能使用 Xib 進行實現(xiàn)忿项。

對此我一直抱著贊否兩論的觀點。在實際工作時寞酿,同一 Storyboard 中存在大量 ViewController 十分容易沖突是一個不爭的事實脱柱,掉進這個坑的人有可能還進行過 xml 修正。但是這個鍋 Storyboard 不背惨好。一部分人可能因此選擇了棄 Storyboard 從 Xib 之路随闺,我也一度徘徊是否這才是正道。但是很顯然的是逗鸣,Storyboard 從一開始就不是為了代替 Xib 而來绰精。

除了 UI 設(shè)置的相似部分以外笨使,Storyboard 更重視畫面之間的關(guān)聯(lián)和遷移,而 Xib 作為通用組件的模版應(yīng)該是不二的選擇硫椰。

在 P-OOP 中靶草,將會存在大量的 dialog,盡管可以很容易的使用 Present Modally 來實現(xiàn)裕寨,不過為了保持系列產(chǎn)品的風(fēng)格一致性派继,需要考慮如何以比較好的方式來實現(xiàn)共通的 header 和 footer 樣式∏烀ǎ考慮過很多方案绅络,比如:

  1. 將 footer 和 header 集成在同一個 view 中嘁字,并添加一個 content view纪蜒,最終在某 controlelr view 中將上述 view 與實際從另一個 xib 中載入的 content view 組合寻行,完成組裝。但是存在一個比較顯著的缺點杆烁,實際可見的 controller view 所呈現(xiàn)的內(nèi)容并不是很直觀简卧,果然還是必須看代碼才能梳理清楚。

  2. 將 footer 和 header 以及一個 content view 集成在同一個 controller view 中析校。在代碼中按照要求載入 content铜涉,代理方法之類變得容易管理了一些,但是更糟糕的是這個 controller 的代碼終將成為垃圾場的吊奢。纹烹。。那加入繼承呢铺呵?有些小題大做?

果然簡潔才是最高的幻林,將 footer 和 header 完全獨立為兩個 view宴卖,按需載入症昏。結(jié)合 @IBInspectable 和 @IBDesignable 可以說是比較完美了父丰,從畫面設(shè)計到遷移等都很清晰掘宪。不足一提的小缺點是使用時候的 auto layout 的設(shè)置可能存在一些重復(fù)操作 (比如 Auto Layout 之類的)攘烛,若考慮 Model 除了 form sheet 以外可以是 full screen坟漱,后者需要在頂部額外預(yù)留 20px,這樣一來反而變得巧妙了腥寇。

也許過幾天自己的想法又發(fā)生了細微變化觅捆,但簡潔清晰無論何時都不會太壞。

心得

Storyboard Reference

Storyboard 容易引發(fā)沖突掂摔,這句話在 Storyboard Reference 面前是不成立的赢赊。

Storyboard Reference 第一次出現(xiàn)在 Xcode 7释移,可以從組件庫中找到它,并自行進行配置和關(guān)聯(lián)趋观,十分簡單锋边,無需贅述。即使是一個已經(jīng)完成且十分繁雜的 Storyboard剩辟,也可以選中想要分離的 Storyboard贩猎,通過 Editor -> Refactor to Storyboard 來實現(xiàn)萍膛。比如,使用了兩個 Container View艇棕,默認情況下此時畫面中存在三個 controller,對其進行分離之后沼琉,變成了這樣:

storyboard_reference.png

Loadable Nib

將 Xib 組件的載入?yún)f(xié)議化打瘪,其中一個目的是為了類型安全闺骚,另一個目的是為了減少重復(fù)代碼。

    protocol Loadable: class {
        static var nibName: String { get }
    }
    
    extension Loadable {
        static var nibName: String { return String(describing: Self.self) }
    }

UIView 進行擴展借杰,要求被載入的 view 遵循 Loadable 協(xié)議:

    extension UIView {
        func instantiateFromNib<T: UIView>(_:T.Type) -> T where T: Loadable {
            if let nib = UINib(nibName: T.nibName, bundle: nil).instantiate(withOwner: nil, options: nil).first as? T {
                return nib
            } else {
                fatalError("Nib \(T.nibName) is not exist ?!")
            }
        }
        
        func instantiateFromNibOwner<T: UIView>(_:T.Type) where T: Loadable {
            let bundle = Bundle(for: type(of: self))
            if let nib = UINib(nibName: T.nibName, bundle: bundle).instantiate(withOwner: self, options: nil).first as? UIView {
                nib.frame = self.bounds
                nib.autoresizingMask = [.flexibleWidth, .flexibleHeight]
                self.addSubview(nib)
            } else {
                fatalError("Nib \(T.nibName) is not exist ?!")
            }
        }
    }

簡潔的初始化:

    let view:ClassName = self.instantiateFromNib(ClassName.self)
    self.instantiateFromNibOwner(ClassName.self)

后來發(fā)現(xiàn)一個名為 Reusable 的庫蔗衡,其中除了這一部分的實現(xiàn)之外绞惦,還有對 Cell 甚至是 Storyboard 和 ViewController 的重用洋措,十分強大。

回到這一部分的實現(xiàn)菠发,略有區(qū)別的地方在于:

  1. Reusable 在初始化 nib 的時候選擇了擴展協(xié)議王滤。
  2. File's Owner 的情況下,Reusable 使用了 Auto Layout滓鸠。由于我們的 P-OOP 項目對應(yīng)的設(shè)備尺寸不多雁乡,所以像是部分彈出框就沒有對應(yīng) Auto Layout,所以就直接從 frame 的尺寸下手了糜俗。踱稍。

追記:把這部分實現(xiàn)和例子提了出來放在了 Github 上~

@IBDesignable 和 @IBInspectable

@IBDesignable 可以用于視圖的實時渲染,@IBInspectable 可以用于定義運行時屬性悠抹。

舉個例子來說:首先在定義一個 DialogHeaderView珠月,標記為 @IBDesignable,將它的 headerTitle 屬性設(shè)置為 @IBInspectable

    @IBDesignable class DialogHeaderView: UIView {
    
        @IBInspectable var headerTitle: String = "" {
            didSet {
                navigationBar.topItem?.title = self.headerTitle
            }
        }
        ...   
    }

然后向目標視圖添加一個 UIView啤挎,并將類定義為 DialogHeaderView,此時在 Attribuite Inspector 中可以直接設(shè)置屬性:

IB1.png

之后即會反映在運行時屬性欄中:

IB2.png

不過構(gòu)建失敗的時候還是挺多的卵凑,不妨通過 Editor -> Debug Selected Views 來調(diào)試一下選中的視圖侵浸。

類型安全

除了定義上面的 Loadable 協(xié)議旺韭,在類型安全這個問題上還可以進一步再做一些工作氛谜。

存在 Storyboard掏觉,Segue 的定義也就會有存在,由于 identifier 的定義是字符串值漫,防不勝防澳腹,不匹配的情況還是會時而發(fā)生。這時候使用 R.swift 就能夠完全解消這個擔(dān)憂了杨何。

R.swift 被廣泛使用于解決類型安全的問題酱塔,圖片、字體危虱、本地化等等都受益于此羊娃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蕊玷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子弥雹,更是在濱河造成了極大的恐慌垃帅,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剪勿,死亡現(xiàn)場離奇詭異贸诚,居然都是意外死亡,警方通過查閱死者的電腦和手機厕吉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門酱固,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人头朱,你說我怎么就攤上這事运悲。” “怎么了髓窜?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵扇苞,是天一觀的道長。 經(jīng)常有香客問我寄纵,道長鳖敷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任程拭,我火速辦了婚禮定踱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘恃鞋。我一直安慰自己崖媚,他們只是感情好亦歉,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著畅哑,像睡著了一般肴楷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荠呐,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天赛蔫,我揣著相機與錄音,去河邊找鬼泥张。 笑死呵恢,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的媚创。 我是一名探鬼主播渗钉,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钞钙!你這毒婦竟也來了鳄橘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤歇竟,失蹤者是張志新(化名)和其女友劉穎挥唠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焕议,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡宝磨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了盅安。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唤锉。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖别瞭,靈堂內(nèi)的尸體忽然破棺而出窿祥,到底是詐尸還是另有隱情,我是刑警寧澤蝙寨,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布晒衩,位于F島的核電站,受9級特大地震影響墙歪,放射性物質(zhì)發(fā)生泄漏听系。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一虹菲、第九天 我趴在偏房一處隱蔽的房頂上張望靠胜。 院中可真熱鬧,春花似錦、人聲如沸浪漠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽址愿。三九已至该镣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間必盖,已是汗流浹背拌牲。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歌粥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓拍埠,卻偏偏與公主長得像失驶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子枣购,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

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