使用Storyboards開發(fā)的10個小技巧
在這里我將著重講述10件事情,而不會去全面講述如何使用Storyboard去創(chuàng)建一些事物。這些知識點沒有特定的順序,但它們也許可以幫到你在這條道路上前行。
Storyboard是我花時間鉆研最多的一個領(lǐng)域。我非常喜歡可視化編程。只需要簡單地將項目拖到畫布中,更新位置信息,再設(shè)置一些描述信息,就已創(chuàng)建了一個用戶界面而不用編寫任何代碼。這非常重要,因為用戶界面的代碼可以很快讓你的代碼變得一團糟。
當我參與到一個新的項目時,我首先要做的就是找到其中的Storyboard。這是概覽程序整體框架的一處重要之地。
假如沒有使用可視化編輯器,你就需要手動化操作才能發(fā)現(xiàn)工作的進展。你在代碼中來回往復耗費大量時間,也只能大致了解給定的視圖的情況。您可以明確參考設(shè)計文件或運行應用程序并導航到所需的區(qū)域,但我更希望避免這種情況。***,在某些情況下,調(diào)整界面組件成為一個繁瑣的過程。你不斷編譯并運行應用程序去驗證它們是否都在正確地位置,而不是通過Storyboard快速調(diào)整。
看看,只是創(chuàng)建右邊這么一個簡單的界面就編寫了這么多的代碼,我甚至還沒有編寫任何自動布局代碼來幫助我們定位。我知道會有頑固的代碼狂人。但我還是不想這些讓我的代碼膨脹,這實在是讓人不快。不要誤會我。對于初學者來說,這樣做的價值是理解如何通過代碼創(chuàng)建一個用戶界面。通過一個給定的用戶界面,你有了一個大概的認識,知道它能做什么。而不是查閱文檔。
列表
也許可以歸為一件,不過不用在意
你不需要將整個程序搭建在一個故事板中??梢詫⑺鼈兎殖珊脦讉€故事板。假設(shè)有管理面板,設(shè)置面板,以及主面板。當你的程序擴大后可以節(jié)省你的很多精力。在團隊中工作時與故事板交互也會變得輕松,而且查找需要的故事板也會更快捷。
什么是exit segue,如何使用它
首先,我說一下什么是segue。假設(shè)你現(xiàn)在的故事板中有兩個場景,其中***個場景中有一個按鈕。當你右擊場景1的按鈕,然后拖動到場景2,你這樣就是創(chuàng)建了一個segue。
現(xiàn)在假設(shè)我們選擇present modally。該模態(tài)表示這是用戶優(yōu)先關(guān)注的場景。這沒有簡單的方法來回到***個場景,就像你可能看過的如果你推送一個場景到導航棧上。我們可以創(chuàng)建一個委托來通知***個控制器我們已經(jīng)完成。但這樣有些乏味,我們也可以發(fā)送通知給***個控制器,但這就是有點大材小用。這是一個機會使用exit segue,exit segue就像segue一樣工作,不同的是會返回到執(zhí)行UIStoryboardSegue動作的地方。這就是關(guān)鍵!
通過你創(chuàng)建的segue,exit segue可以一直后退導航,無論segue是在那創(chuàng)建的,都可以找到exit segue。
查看一下下方的完整地視圖結(jié)構(gòu)。
如果你只是右擊按鈕的exit segue指示器,你不會看到任何東西。它需要檢測你在目標控制器中創(chuàng)建一個UIStoryboardSegue動作的方法(綠色箭頭指向)。例如:
- @IBAction func unwindToSceneA(unwindSegue: UIStoryboardSegue) {
- // be sure to give your unwind segue an identifier so you know where we're coming from
- }
Storyboard(故事板)跳轉(zhuǎn)
你無需在故事板中繪制漂亮的segue到你想去的地方。你只需初始化故事板以及獲取你想要展示的控制器。一旦你有了控制器,你可以調(diào)用必要的顯示方法。
- var storyboard: UIStoryboard = UIStoryboard(name: "Settings", bundle: nil)
- var modal: UIViewController = storyboard.instantiateViewControllerWithIdentifier("settingsStoryboardId") as UIViewController
- self.presentViewController(modal, animated: true, completion: nil)
- /* If you're fetching a controller in the same storyboard you're already on,
- * then you can skip initializing a new UIStoryboard object.
- */
- var modal: UIViewController = self.storyboard?.instantiateViewControllerWithIdentifier("customStoryboardId") as UIViewController
- self.presentViewController(modal, animated: true, completion: nil)
如果花所有時間去構(gòu)建并運行應用程序以觀察用戶界面是否調(diào)整到你想要的結(jié)果,是很乏味的。在處理自動布局時尤其如此。
現(xiàn)在打開預覽編輯器,你可以修改視圖,觀察它如何變化。你也可以按下左下角助理編輯面板上的+按鈕,以便在多個屏幕尺寸預覽界面。
#p#
讓手指休息一下
如果你有一個按鈕需要連接到源代碼中,你可以右鍵單擊,然后拖一條線到源文件中為你生成一個outlet.
此外,對于一個給定的事件,你可以通過單擊再拖到你的源文件來生成一個action。
以上操作的最終結(jié)果。
那,為什么需要做這些操作呢? 這么說吧,最明顯的就是action。如果你不創(chuàng)建一個@IBAction函數(shù),那么當你按下按鈕的時候不會有任何事情發(fā)生。你可以假設(shè)需要添加一些代碼來改變UIImageView中最初設(shè)置的的圖片。為了改變這個圖片我們就需要一個@IBOutlet以便我們訪問它。
避免極其復雜的控制器
盡管你的控制器可以管理大量子視圖,但你的風險在于一層一層的添加視圖,這會使事情完全被破壞。很快你就會發(fā)現(xiàn),你偏離了使用可視化編輯器的目的--提供清晰的視圖層次。如果你有一個復雜的視圖結(jié)構(gòu),那么是時候考慮這些設(shè)置。
你可以使用一個xib,或者你可以添加一個容器視圖對象到你的場景,并隱藏它直到需要的時候。通常我使用xib,但在某些情況下則使用容器視圖對象。
當你添加一個xib的同時還會添加一個源文件,你將使用它來初始化xib.例如,我們創(chuàng)建了ExampleView.xib以及一個漂亮的場景。為了加載這個視圖我們需要創(chuàng)建ExampleView.swift以及初始化這個xib。
- import UIKit
- class ExampleView: UIView {
- // normal initialization
- override init(frame: CGRect) {
- super.init(frame: frame)
- self.addExampleViewSubview()
- }
- // will be loaded if we use this class in a storyboard, for example
- required init(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- self.addExampleViewSubview()
- }
- func addExampleViewSubview() {
- var xib = NSBundle.mainBundle().loadNibNamed("ExampleView", owner: self, options: nil)
- var view: UIView = xib.first as UIView
- view.frame = self.frame
- self.addSubview(view)
- }
- }
占位符約束
這是給那些喜歡混合使用代碼與故事板操縱約束的人的。即使我個人盡可能地避免在代碼中編寫約束,但這對于那些不屬于故事板的視圖確實是很有作用的。
假如你試圖在代碼中創(chuàng)建約束,且需要與故事板中的用戶界面交互,這可能會是一個非??膳碌慕?jīng)歷。不過不要害怕,你可以很輕松地告訴Xcode這個特定約束是一個占位符。這意味著在構(gòu)建和運行應用程序時它將被忽略。
默認的試圖控制器
你可能需要更改哪個場景與故事板一起加載。在早期版本的Xcode中你也許會選擇一個場景,然后選擇**Is Initial View Controller**。在Xcode的***版本變了?,F(xiàn)在你需要搜索對象庫,找到 **Storyboard Entry Point**,然后你可以拖拽到想要的場景。這其中一次只能有一個是活躍的,所以你可以可以拖拽它到你想想要的任一控制器中。
為什么你會擔心入口點發(fā)生改變?就我個人而言,我使用它來測試不同的控制器,我不想創(chuàng)建大量的按鈕才能進到控制器里去。如果你只是更新故事板的入口點,它就會立即加載。
自定義Segue轉(zhuǎn)場效果
如果你選中一個segue,你可能已經(jīng)注意到,它有一些預加載的轉(zhuǎn)場效果,比如垂直覆蓋、水平翻轉(zhuǎn)、淡入淡出以及部分卷曲等。如果你想要更多的自定義效果呢?在這種情況下你需要創(chuàng)建一個自定義UIStoryboardSegue。
舉個簡單的粟子,創(chuàng)建一個新的Swift文件,取名為**CustomSegue**。 當我們的segue被執(zhí)行的時候(上面的按鈕被點擊),下面這段代碼也會被執(zhí)行。
- import UIKit
- class CustomSegue: UIStoryboardSegue {
- var startingPoint: CGPoint = CGPoint(x: 0, y: 0)
- override func perform() {
- var source = self.sourceViewController as UIViewController
- var destination = self.destinationViewController as UIViewController
- // Add the destination view as a subview (temporarily)
- source.view?.addSubview(destination.view)
- // Set the start scale
- destination.view.transform = CGAffineTransformMakeScale(0.05, 0.05)
- // Original center point
- var originalCenter = destination.view.center
- destination.view.center = self.startingPoint
- UIView.animateWithDuration(0.225, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
- destination.view.transform = CGAffineTransformMakeScale(1.0, 1.0)
- destination.view.center = originalCenter
- }) { (finished) -> Void in
- destination.view.removeFromSuperview()
- source.presentViewController(destination, animated:false, completion:nil)
- }
- }
- }
按下鈕按時,這將從我們設(shè)置的一個起始位置展開目標視圖。在這種情況下,我設(shè)置起始位置為場景1中按鈕的中心位置(源場景)。
- override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
- let custom = segue as CustomSegue
- custom.startingPoint = self.nextImage.center
- }
在故事板文件中我們選擇從場景1到場景2的segue。更改Segue為Custom,然后輸入Segue類來匹配我們剛剛創(chuàng)建的一個CustomSegue。
避免源代碼管理的噩夢
對于那些在團隊中的人來說,雖然他們也在逐漸變得更好,但當涉及到源代碼管理時,故事板仍是一個大痛處。這也是為什么你應該將故事板拆分成若干個。如果你可以避免這個,請確保同一時刻只有一個人操作故事板。這會避免其他人提交故事板的更改到項目中產(chǎn)生的沖突。即使這并不那么容易去避免,但請做好準備防止這種情況出現(xiàn)。這也許是團隊與小公司不想使用故事板***的原因。
盡管當我與的團隊共享故事板時很有可能會導致源代碼控制的沖突,我仍然覺得,速度和效益的重要性大于修補因為沖突導致的惱人補丁。在大多數(shù)情況下我確保其他人避免與我同時處理。但是,它仍然一次又一次發(fā)生。
這里是我如何處理沖突的方法:
- (***道防線)首先主動避免它。在與故事板工作時我經(jīng)常盡早的提交,并且對其他也在與這個故事板工作的人打個招呼。當與其他人一起工作時,盡量保持小任務量的工作,以及互相幫助。不要推送整體的大更新。
- 如果我遇到了沖突,我會通過差異工具[Kaleidoscope](http://www。kaleidoscopeapp。com/)來瀏覽。這確實需要一些經(jīng)驗來理解故事板的原理。如果你還沒看過,現(xiàn)在就是時候。右鍵點擊 storyboard > open as > source code,觀察控制器區(qū)域(包括連接信息)是如何陳列布局的。
- (糟糕的情況)我找出了誰做的***的更改,誰接收的這些變化信息,覆蓋其了其他什么,然后我們會恢復這些改變。
我做過一些大型的項目。雖然這些合并的issues不是經(jīng)常嚴重到diff工具不能恢復。但你可以獲得更多的經(jīng)驗。
我不能強調(diào)***點是足夠的。積極主動很重要。知道你的團隊是什么樣地情況。如果你有一個令人難以置信的復雜的故事板,就將它板劃分成不同的區(qū)域。
拿走不謝
故事板是非常有用的,尤其是對于那些非常直觀的東西。當做原型時,也可以給你一個不錯的速度優(yōu)勢。無需為代碼煩憂,你可以快速將各種元素放在適當?shù)牡胤?,連接它們,然后從驅(qū)動界面的邏輯開始做起。