iOS 9系列:Storyboard Reference、Strong IBOutlet以及Scene Dock

1445501965993069.png

本文由CocoaChina譯者小袋子(博客)翻譯原文:Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9
在這個教程中,我想要聊一些有關于Xcode 7中Interface Builder的新特性,我相信這將會改變你對Storyboards的看法。
Strong 引用的 IBOutlet
Apple已經對Xib和Storyboard文件做了很多優化。并且由于這些優化,你現在可以將IBOutlet定義為strong,而不是weak。Apple曾在上一屆的WWDC上指出這一點,因此讓我們來看一下其中的更多細節。你可以從 這個文檔 中找到管理Nib文件中對象生命周期的章節:
Outlet一般來說應該為weak,除了在nib文件 ( 或者iOS中,storyboard scene) 中的File’s Owner的頂級對象,這個對象可以是strong。你創建的Outlets應該為weak,原因如下:
你創建的一個 view controller 視圖的子視圖或者 window controller 窗體視圖的 Outlets,是對象之間的弱引用,不應該有依賴關系。

strong的outlet通常是特殊的framework類(如:UIViewController 視圖的 outlet,或者 NSWindowController 視窗的 outlet)。

正如這個段落所解釋的一樣,view controller視圖的子視圖 outlet應該為 weak,因為這個視圖已經被nib文件的頂級對象所擁有了。然而,當一個Outlet被定義為weak指針時,ARC會在編譯期間調用以下函數:

id objc_storeWeak(id *object, id value);

這個函數把對象的值作為key,并把它添加到table中。這個table被稱為weak table。ARC使用這個table去存儲應用中的所有的weak指針。現在,當對象被deallocated時,ARC將會指向weak table并且將weak引用置為nil。同時,ARC將會調用:

void objc_destroyWeak(id * object);

緊接著,注銷這個對象并再次調用objc_destroyWeak:

objc_storeWeak(id *object, nil);

這種weak引用關聯的生命周期是strong引用的2-3倍。所以,通過避免簡單地定義outlets為strong,使用弱引用是一種運行期間的通用做法。
我想這個決策與已廢棄的viewDidUnload方法有關。直到iOS 5,這個方法被用于清空在低內存環境下的視圖。正如文檔中解釋的那樣:
在iOS 5之前,當發生低內存警告或者當前view controller的視圖不被需要時,在視圖被釋放之后,系統會選擇性地調用這個方法。這個方法讓你可以進行最后的清理工作。如果你的視圖存儲了視圖或者其子視圖的單獨引用,你應該使用這個方法去釋放這些引用。
在那時,定義一個屬性為weak是有意義的,因為這就不用在viewDidUnload額外地釋放對象。但是在iOS 9中,我相信我們已經有足夠的時間去避免使用這個方法。因此,在IBOutlets定義weak是沒意義的。
現在 Storyboard 的幾個限制
Apple是在iOS 5中開始引入storyboards的。在此之前,使用Interface Builder的nib文件是創建UI的唯一途徑。在iOS開發中,單個文件中操縱多個nib文件是很普遍的。然而,為了理解應用流以及view controller如何連接在一起,開發者需要去每一個view controller類內去找出跳轉到下一個界面的橋接點。這是一個非常耗費時間的工序,尤其當你不是應用的原始開發者時。
Apple提出Storyboards用以簡化這個過程,并幫助開發者能夠對整個應用程序流有完全的控制。除此之外,storyboards允許你在一個文件中擁有一個view controller視圖(通過添加 .storyboard文件)。用這種方式,你可以看到整個程序的流狀態,并且能夠方便地理解view controller的連接關系。然而,storyboards也引出了一些問題。把所有的nib文件都放在一個文件中顯然是非常便利并且能完美工作,但是這只是在你為單人開發的前提下。只要你的團隊擴大了,你會使用版本控制,例如git或者subversion,這時你就會討厭storyboards。因為,當把修改合并到一個通用的git branch時,就會產生沖突,而解決此類沖突是很頭疼的。在編譯期間,nib會被編譯成XML文件。所以,為了解決合并沖突,你需要比較兩個巨大的XML文件,并且要嘗試理清哪部分是你修改的,哪部分是你同事修改的。此外,Apple經常修改這個文件格式。所以,試圖去理解并且反轉storyboard格式是非常浪費時間的。
例如,在iNVASIVECODE(這是作者所在的公司),我們傾向于使只用storyboards去構建app原型。我們的設計師能夠在幾個小時內設計出一個能夠在iOS設備上運行的原型,有時候只需要幾分鐘。這樣可以在不寫一行代碼的情況下使用storyboards。所以,storyboards對于構建原型來說是非常方便的,但是不建議在開發期間使用。
另一個storyboard的重要局限是不能添加不屬于一個場景體系的視圖。我個人認為跟前面所說的合并問題相比,這是一個更為致命的限制。只要能夠使用,我必定會使用IB。我喜歡這個,因為這可以避免寫代碼。但是使用storyboards,不能添加場景體系以外的視圖。因此,當我需要額外的視圖時,我就強迫自己去使用nib。
Storyboards還有一個額外的局限就是轉場動畫問題。在iOS 7及之后的iOS 8,Apple提出了在兩個view controller之間定制一個轉場動畫的新方法。當你運行一個segue時,這個新方法需要創建不能使用storyboard的特殊對象。所以,如果你想要添加定制轉場動畫的方法到你的view controllers,你要避免使用storyboards。
但是猜猜看!Xcode 7和iOS 9為我們解決了所有的這些問題。
Storyboard Reference
在Xcode 7中,我們有一個在多個storyboards中組織scenes的新方法,并且能對它們進行引用。讓我們來看一個實踐的例子。下載 這個我已經準備好的例子。打開它,并且選擇Main.storyboard文件。我已經為了準備好了一系列組織在一個tab bar controller下view controller。每一個tab包含一個navigation controller。下面的圖片強調了示例項目的storyboard部分。

1445502506602936.png

正如你所看到的那樣,tab bar controller包含了三個navigation controller。每一個navigation controller控制著不同的視圖控制器。現在,想象一下在這個項目里和其他開發者一起工作。正如我前面描述的那樣,使用同一個storyboard文件是非常令人頭疼的,因為你們每個人都會修改它。你可以把著三個navigation分支分割成三個storyboard文件。然而,當你準備在運行期從一個storyboard跳轉到另外一個時,你必須加載相應的storyboard文件。這需要增加額外的代碼。
xcode 7允許你創建多個storyboards,并且可以方便地操縱它們。選擇頂部的navigation controller 以及兩個view controller,如下圖所示:
1445502568715361.png

選擇好之后,打開菜單欄的Editor,然后選擇Refactor to Storyboard(如圖)
1445502615641502.png

為新的storyboard取一個名字(如圖)。我將它命名為First.storyboard。
1445502671957526.png

點擊保存。正如你所見到的那樣,一個新的storyboard已經被添加到你的項目中了。讓我們回到Main.storyboard,你將會看到如下的對象。
1445502704634152.png

這個稱之為Storyboard Reference,它確實為新建的First.storyboard的引用,并且替換了先前選擇的三個view controller。最棒的是如果你雙擊storyboard引用,Xcode 7會打開所引用的storyboard。因此,當你想要控制應用流時,你可以方便地導向不同的storyboard。在運行期間,當segue指向的一個Storyboard Reference被執行時,這個被引用的storyboard中的初始化view controller會被加載。此外,Storyboard References還能夠引用相同的storyboard。
另外,你也可以手工創建一個新的storyboard,然后添加一個Storyboard Reference到起始的storyboard中。讓我們來試一下。
創建一個新的storyboard并命名為Third.storyboard。在Main.storyboard文件中,從Object Library中添加新的Storyboard Reference。選擇Storyboard Reference并且打開相應的Attributes Inspector。如下圖所示:
1445502735552734.png

在這個字段中,選擇你想要引用的storyboard(在我們的例子中是Third)。如果這個字段為空白,則被引用的storyboard是定義的Storyboard Reference。Reference ID指向在目的storyboard中的一個特定scene。如果你置空的話,初始化view controller會加載。
1445502798712409.png

最后,Bundle字段需要被置為包含目的storyboard的bundle。如果你留空的話,就會使用源storyboard的bundle。
在Third.storyboard文件中,你需要添加一個新的view controller并將其作為初始化的view controller。之后,只要view controller是Main storyboard的一部分,你可以都可以運行app并且導航到那里。
所有,現在你可以在多個文件里組織你的storyboard,并且可以保持這些storyboard的引用。此外,每一個storyboard能夠被分配給一個不同的開發者,而你不需要去考慮view controller間的連接組合。這真是非常方便。
Scene Dock and Extra Views
這是我最喜歡的特性。現在,我能夠在storyboard中添加在scene體系外的視圖。為了讓你明白它使如何工作的,我們先創建一個新的項目。將其命名為ExtraView,打開Main storyboard,在頂部的First Responder和Exit之間添加一個新的view。如下圖所示(這個叫做Scene Dock):
1445502912235844.png

把這個view的大小調整為 1500×120 像素。然后在這個view的頂層添加一個大小為 240×112 的小view。把這個視圖放到大視圖的中心,然后增加頂部和底部的約束 (constants = 8),寬度約束(constant = 240) 以及水平居中的約束。然后添加一個scrollview到view controller中,將其居中,并添加trailing和leading space約束 (constant = 0),高度約束(constant=128),最后增加垂直居中約束。在ViewController.swift中,添加下列兩個outlet:

@IBOutlet  var externalView: UIView! 
@IBOutlet  var scrollView: UIScrollView!

將它們連接到scrollview以及外面的view。最后,添加viewDidAppear:方法:

override func viewDidAppear(animated: Bool) {
  super.viewDidAppear(animated)
  scrollView.contentSize = externalView.frame.size
  scrollView.addSubview(externalView)
}

然后運行項目,可以看到的是,你現在可以添加額外的視圖(可以任意添加),并且可以在運行期間很方便地加載出來。你可以 下載 這個示例來加深理解。
定制轉場動畫
這是Xcode 7中storyboard另外一個很酷的新特性。具體的細節我將會留到之后發布的文章,這里我只想先給你一些你能做什么的想法。如果你在多storyboard項目中選擇任意的action segue,并且打開Attributes Inspector,你將會看到一個新的字段Segue Class,正如下圖所示:

1445503461774466.png

你可以創建一個UIStoryboardSegue的子類,然后遵從UIViewControllerTransitioningDelegate 協議。然后,在類中實現animationControllerForPresentedController: presentingController: sourceController: 以及 animationControllerForDismissedController:。此外,你還需要創建兩個NSObject的子類,遵從UIViewControllerAnimatedTransitioning delegate。在這些類中,你必須實現兩個方法:transitionDuration: 和 animateTransition:。
我將會在接下來的文章中介紹其中的細節。
總結
Xcode 7的Storyboards增加了很多便利的新特性。我們現在可以創建storyboard references,在scene體系外增加視圖,并且可以使用新的定制視圖轉場動畫。我還討論了為什么你應該將outlet定義為strong引用而不是weak。
作者介紹
Geppy
Geppy Parziale (@geppyp) is cofounder of InvasiveCode (@invasivecode). He has developed iOS applications andtaught iOS development since 2008. He worked at Apple as iOS and OS X Engineer in the Core Recognition team. He has developed several iOS and OS X apps and frameworks for Apple, and many of his development projects are top-grossing iOS apps that are featured in the App Store.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容