本教程以您在首個(gè)教程(“教程:基礎(chǔ)”)中創(chuàng)建的項(xiàng)目為基礎(chǔ)。您將會(huì)實(shí)踐已學(xué)到的知識(shí),包括視圖、視圖控制器、操作和導(dǎo)航方法。按照界面優(yōu)先的設(shè)計(jì)流程,您還將為 ToDoList 應(yīng)用程序創(chuàng)建某些關(guān)鍵的用戶界面,并將行為添加到所創(chuàng)建的場(chǎng)景中。
本教程將向您講述如何:
完成本教程中的所有步驟后,您的應(yīng)用程序外觀大致是這樣的:
“add-to-do-item”場(chǎng)景的工作模式為豎排,與創(chuàng)建時(shí)一致。要是用戶旋轉(zhuǎn)了設(shè)備會(huì)如何?請(qǐng)?jiān)囍?Simulator 中運(yùn)行應(yīng)用程序來模擬這種情況。
1.請(qǐng)?jiān)?iOS Simulator 中啟動(dòng)應(yīng)用程序。
2.選取“Hardware”>“Rotate Left”(或按下 Command–左箭頭鍵)。
如您所見,文本欄看起來不大對(duì)勁。它只占了屏幕約一半的位置。文本欄本應(yīng)延伸至整個(gè)屏幕,正如豎排模式中顯示的那樣。幸好,Xcode 內(nèi)建有一款功能強(qiáng)勁的布局引擎,稱為“Auto Layout”。關(guān)于場(chǎng)景中要如何放置元素,您可以通過 Auto Layout 將您的意圖描述出來,然后由該布局引擎確定如何以最優(yōu)方案實(shí)現(xiàn)該意圖。使用約束規(guī)則描述您的意圖,它說明了應(yīng)當(dāng)如何放置一個(gè)元素以與另一個(gè)元素相關(guān)聯(lián)、元素應(yīng)有的大小,或者在適用的空間減小時(shí),兩個(gè)元素中的哪一個(gè)應(yīng)當(dāng)先縮小。對(duì)于“add-to-do-item”場(chǎng)景,則需要使用兩類約束:一種用于放置文本欄,另一種用于設(shè)定其大小。
這些約束的設(shè)定工作均可在 Interface Builder 中輕松完成。
1.在項(xiàng)目導(dǎo)航器中,選擇 Main.storyboard。
2.在串聯(lián)圖中,選擇文本欄。
3.在畫布上,按住 Control 鍵從文本欄拖向場(chǎng)景頂部,直到文本欄四周皆為空白區(qū)域。此區(qū)域?yàn)槲谋緳诘母敢晥D。
停止拖移操作時(shí),其位置將出現(xiàn)一個(gè)快捷菜單。
4.從快捷菜單中選取“Top Space to Top Layout Guide”。
在文本欄頂部和導(dǎo)航欄之間,將創(chuàng)建一個(gè)間距約束。
如果出現(xiàn)了其他菜單(比如帶有“Leading Space to Container”菜單項(xiàng)),則表示您沒有垂直地拖到屏幕頂部。Xcode 會(huì)根據(jù)您拖移的方向來判斷您打算生成哪一類約束,并根據(jù)拖移的起始點(diǎn)和結(jié)束點(diǎn)來判斷約束要關(guān)聯(lián)哪些對(duì)象。您可以繼續(xù)嘗試不同的拖移方向,以便了解有哪些約束可用。
5.嘗試完之后,請(qǐng)按住 Control 鍵從文本欄向右拖移到父視圖,以便創(chuàng)建“Trailing Space to Container”約束。
6.按住 Control 鍵從文本欄向左拖移到其父視圖,以便創(chuàng)建“Leading Space to Container”約束。
這些約束指定了文本欄邊緣與其父視圖之間的距離,使它們不發(fā)生變化。也就是說,如果設(shè)備方向發(fā)生改變,文本欄將自動(dòng)伸展以滿足這些約束。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。如果您旋轉(zhuǎn)設(shè)備,文本欄將根據(jù)設(shè)備的方向伸展或收縮到適當(dāng)大小。
如果行為沒能達(dá)到預(yù)期,請(qǐng)啟用 Xcode Auto Layout 調(diào)試功能以獲取幫助。文本欄選定后,請(qǐng)選取“Editor”>“Resolve Auto Layout Issues”>“Reset to Suggested Constraints”,讓 Xcode 設(shè)置上述步驟所描述的約束?;蜻x取“Editor”>“Resolve Auto Layout Issues”>“Clear Constraints”,移除文本視圖上的所有約束,然后試著再次按照上述步驟操作。
盡管添加項(xiàng)目場(chǎng)景能做的有限,但基本的用戶界面都已成型并且初具功能。在一開始考慮清楚布局問題,將為您之后的構(gòu)建奠定堅(jiān)實(shí)基礎(chǔ)。
目前,您已經(jīng)處理過由視圖控制器管理的單個(gè)場(chǎng)景,即一個(gè)可讓您將項(xiàng)目添加到待辦事項(xiàng)列表的頁面。現(xiàn)在,是時(shí)候創(chuàng)建一個(gè)能顯示整個(gè)待辦事項(xiàng)列表的場(chǎng)景了。真是幸運(yùn),iOS 自帶一個(gè)名為表格視圖的內(nèi)建類,它功能強(qiáng)大,專門設(shè)計(jì)用于顯示項(xiàng)目的滾動(dòng)列表。
將帶有表格視圖的場(chǎng)景添加到串聯(lián)圖
1.在項(xiàng)目導(dǎo)航器中,選擇 Main.storyboard。
2.在實(shí)用工具區(qū)域中打開對(duì)象庫。(若要通過菜單命令打開資源庫,請(qǐng)選取“View”>“Utilities”>“Show Object Library”。)
3.將“Table View Controller”對(duì)象從列表中拖出,并放置在“add-to-do-item”場(chǎng)景左側(cè)的畫布上。如有需要,您可以使用畫布右下方的“縮小”按鈕 image: ../Art/zoom_out_2x.png 來獲取足夠的拖放空間。
如果表格視圖中包含內(nèi)容,但嘗試拖到畫布時(shí)卻毫無反應(yīng),那么您拖移的很可能是表格視圖,而不是表格視圖控制器。表格視圖是表格視圖控制器所管理的多個(gè)項(xiàng)目之一,但您需要的是整個(gè)套件,因此請(qǐng)找到表格視圖控制器,并將其拖到畫布。
現(xiàn)在您有了兩個(gè)場(chǎng)景,一個(gè)用于顯示待辦事項(xiàng)列表,另一個(gè)用于添加待辦事項(xiàng)。
當(dāng)用戶啟動(dòng)應(yīng)用程序時(shí),讓他們先看到列表很有必要。因此請(qǐng)告訴 Xcode 您的意圖,把表格視圖控制器設(shè)置為首個(gè)場(chǎng)景。
將表格視圖控制器設(shè)定為初始場(chǎng)景
或者,您可以將初始場(chǎng)景指示器從“add-to-do-item”場(chǎng)景中直接拖到畫布上的表格視圖控制器。 表格視圖控制器將設(shè)定為串聯(lián)圖中的初始視圖控制器,從而成為應(yīng)用程序啟動(dòng)時(shí)載入的首個(gè)場(chǎng)景。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序?,F(xiàn)在,您看到的不是“add-to-do-item”場(chǎng)景及其文本欄,而應(yīng)該是空的表格視圖:一個(gè)由多條水平分隔條劃分成行,但每一行均不包含內(nèi)容的屏幕。
由于您尚未學(xué)習(xí)如何儲(chǔ)存數(shù)據(jù),因此要?jiǎng)?chuàng)建和儲(chǔ)存待辦事項(xiàng),并將它們顯示在表格視圖中還為時(shí)過早。但是要展示用戶界面原型,并不需要用到真實(shí)數(shù)據(jù)。Xcode 允許您通過 Interface Builder 在表格視圖中創(chuàng)建靜態(tài)內(nèi)容。此功能便于您查看用戶界面的表現(xiàn),并且對(duì)于嘗試不同的設(shè)計(jì)概念來說也很有價(jià)值。
在表格視圖中創(chuàng)建靜態(tài)單元格
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。現(xiàn)在,您應(yīng)該能看到一個(gè)表格視圖,其中含有在 Interface Builder 中添加的預(yù)先配置的單元格。可以查看一下新表格視圖在滾動(dòng)時(shí)的整體效果。試試旋轉(zhuǎn)模擬設(shè)備,注意觀察單元格視圖如何配置,才對(duì)其內(nèi)容進(jìn)行了正確布局。在表格視圖中,您可以自由地進(jìn)行大量操作。
完成后,應(yīng)該設(shè)計(jì)如何從這個(gè)表格視圖及其待辦事項(xiàng)列表,瀏覽到您所創(chuàng)建的首個(gè)場(chǎng)景(即用戶可以創(chuàng)建新待辦事項(xiàng)的場(chǎng)景)。
您已經(jīng)在串聯(lián)圖中配置了兩個(gè)視圖控制器,但它們彼此之間沒有連接。場(chǎng)景之間的轉(zhuǎn)場(chǎng),我們稱為過渡。
創(chuàng)建過渡前,您需要先配置場(chǎng)景。首先,在導(dǎo)航控制器中包括待辦事項(xiàng)列表表格視圖控制器。回想之前的“定義交互”,我們知道導(dǎo)航控制器能提供導(dǎo)航欄,并且能夠跟蹤導(dǎo)航堆棧。您將在“add-to-do-item”場(chǎng)景的轉(zhuǎn)場(chǎng)中添加導(dǎo)航欄按鈕。
將導(dǎo)航控制器添加到表格視圖控制器
Xcode 能給串聯(lián)圖添加新的導(dǎo)航控制器、為其設(shè)定初始場(chǎng)景,并在新的導(dǎo)航控制器和現(xiàn)有的表格視圖控制器之間建立關(guān)系。在畫布上,如果您選擇了連接兩個(gè)場(chǎng)景的圖標(biāo),就會(huì)發(fā)現(xiàn)這其實(shí)是一種根視圖控制器關(guān)系。這表示導(dǎo)航欄下方顯示的內(nèi)容視圖將為表格視圖。初始場(chǎng)景設(shè)定為導(dǎo)航控制器,因?yàn)閷?dǎo)航控制器保留了將顯示在應(yīng)用程序中的所有內(nèi)容,它是待辦事項(xiàng)列表和“add-to-do-item”場(chǎng)景的容器。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。在表格視圖上方,您將看到額外的區(qū)域。這是導(dǎo)航控制器所提供的導(dǎo)航欄。
現(xiàn)在,您將為導(dǎo)航欄添加標(biāo)題(關(guān)于待辦事項(xiàng)列表)和按鈕(用于添加更多待辦事項(xiàng))。
該按鈕將變成添加按鈕 (+)。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。導(dǎo)航欄現(xiàn)在應(yīng)該有了標(biāo)題,并顯示有一個(gè)添加按鈕。該按鈕暫時(shí)沒有任何作用。之后您將修復(fù)這個(gè)問題。
您想讓添加按鈕調(diào)用“add-to-do-item”場(chǎng)景。該場(chǎng)景已經(jīng)配置好了,它正是您所創(chuàng)建的首個(gè)場(chǎng)景,只是還沒有連接其他場(chǎng)景。通過 Xcode,您能輕松地配置添加按鈕,使其輕按一下便可調(diào)出其他場(chǎng)景。
拖移停止的位置,將出現(xiàn)一個(gè)標(biāo)題為“Action Segue”的快捷菜單。
通過該菜單,Xcode 能讓您選取當(dāng)用戶輕按添加按鈕時(shí),待辦事項(xiàng)列表到“add-to-do-item”視圖控制器之間的轉(zhuǎn)場(chǎng)所使用的過渡類型。
Xcode 將設(shè)置過渡,并將“add-to-do-item”視圖控制器配置為顯示在導(dǎo)航控制器中,您將在 Interface Builder 中看到導(dǎo)航欄。
現(xiàn)在,項(xiàng)目中可能出現(xiàn)了數(shù)個(gè)警告。請(qǐng)繼續(xù)并打開“Issue”導(dǎo)航器來查看問題所在。
由于您將“add-to-do-item”場(chǎng)景添加到了導(dǎo)航堆棧,它現(xiàn)在將顯示導(dǎo)航欄。該欄將導(dǎo)致您文本欄的邊框下移,從而無法滿足之前指定的 Auto Layout 約束。好在這并不難解決。
1.在大綱視圖或畫布上,選擇文本欄。
2.在畫布上,打開“Resolve Auto Layout Issues”彈出式菜單 ,然后選取“Update Constraints”。 或者,您可以選取“Editor”>“Resolve Auto Layout Issues”>“Update Constraints”。 約束將更新,同時(shí) Xcode 警告會(huì)消失。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。您可以點(diǎn)按添加按鈕,并瀏覽到表格視圖中的“add-to-do-item”視圖控制器。由于您使用的是帶 push 過渡的導(dǎo)航控制器,因此向后導(dǎo)航已為您處理完畢。這表示您可以通過點(diǎn)按返回按鈕來回到表格視圖。
一般情況下,push 導(dǎo)航的功能是正常的,但添加項(xiàng)目時(shí)則不太一樣。Push 導(dǎo)航設(shè)計(jì)用于深層次界面,即無論用戶選定哪一項(xiàng),您都能為其提供更多相關(guān)信息。而另一方面,添加項(xiàng)目是一種模態(tài)操作,即用戶執(zhí)行某個(gè)完整且自包含的操作,然后從場(chǎng)景返回到主導(dǎo)航。此類型場(chǎng)景恰當(dāng)?shù)谋硎龇绞綖?modal 過渡。
Modal 視圖控制器不會(huì)添加到導(dǎo)航堆棧,因此它沒有從表格視圖控制器的導(dǎo)航控制器中獲得導(dǎo)航欄。但是您可能想要保留導(dǎo)航欄,給予用戶視覺上的連續(xù)性。要在模態(tài)展示時(shí)為“add-to-do-item”視圖控制器添加導(dǎo)航欄,請(qǐng)將它嵌入其自身的導(dǎo)航控制器中。
和之前一樣,Xcode 會(huì)在視圖控制器的頂部添加導(dǎo)航控制器,并顯示導(dǎo)航欄。接著,配置此欄以將標(biāo)題及“Cancel”和“Done”這兩個(gè)按鈕添加到該場(chǎng)景。稍后,會(huì)將這些按鈕鏈接到操作。
檢查點(diǎn):運(yùn)行您的應(yīng)用程序。點(diǎn)按添加按鈕。您仍將看到添加項(xiàng)目場(chǎng)景,但返回瀏覽待辦事項(xiàng)列表的按鈕將消失,取而代之的是您添加的“Done”和“Cancel”這兩個(gè)按鈕。這些按鈕尚未鏈接到任何操作,因此您雖然可以點(diǎn)按它們,但不會(huì)有任何反應(yīng)。下個(gè)任務(wù),我們將配置按鈕以完成或取消編輯新的待辦事項(xiàng),并使用戶返回待辦事項(xiàng)列表。
至今您所完成的配置工作,都無需編寫任何代碼。不過,配置整個(gè)“add-to-do-item”視圖控制器還是需要代碼的,同時(shí)還得有放代碼的位置。此時(shí),Xcode 已將“add-to-do-item”視圖控制器,以及表格視圖控制器,配置為基本的視圖控制器。如果給自定代碼預(yù)留位置,您需要為每一個(gè)視圖控制器創(chuàng)建子類,然后配置界面以使用這些子類。
首先,需要處理“add-to-do-item”視圖控制器場(chǎng)景。自定視圖控制器類的名稱為 XYZAddToDoItemViewController
,因?yàn)榇艘晥D控制器所控制的場(chǎng)景,會(huì)為您的待辦事項(xiàng)列表添加新項(xiàng)目。
現(xiàn)在,自定視圖控制器的子類已經(jīng)創(chuàng)建,您需要讓串聯(lián)圖使用自定類,而不是使用基本視圖控制器。串聯(lián)圖文件是應(yīng)用程序運(yùn)行時(shí)所使用的對(duì)象的相關(guān)配置。應(yīng)用程序的運(yùn)行機(jī)理,能將串聯(lián)圖最初使用的基本視圖控制器,智能地替換成自定視圖控制器,但首先您需要向串聯(lián)圖下達(dá)該命令。
將類識(shí)別為某個(gè)場(chǎng)景的視圖控制器
運(yùn)行時(shí),串聯(lián)圖將創(chuàng)建 XYZAddToDoItemViewController 的實(shí)例,即您的自定視圖控制器子類來代替基本的 UIViewController。請(qǐng)注意 Xcode 已將“add-to-do-item”視圖控制器場(chǎng)景的描述,從“View Controller – Add To-Do Item”更改為“Add To Do Item View Controller – Add To-Do Item”。Xcode 知道此場(chǎng)景當(dāng)前正在使用自定視圖控制器,因此它解釋了自定類的名稱,以方便您理解串聯(lián)圖上的內(nèi)容。
現(xiàn)在,請(qǐng)對(duì)表格視圖控制器執(zhí)行相同操作。
請(qǐng)?jiān)俅未_定,已在串聯(lián)圖中配置了自定表格視圖控制器 XYZToDoListViewController。
現(xiàn)在,您可以給視圖控制器添加自定代碼了。
除了 push 和 modal 過渡外,Xcode 還提供 unwind 過渡。此過渡允許用戶從一個(gè)給定場(chǎng)景返回上一個(gè)場(chǎng)景,并提供位置讓您添加代碼,以在用戶導(dǎo)航切換場(chǎng)景時(shí)執(zhí)行。您可以使用 unwind 過渡從 XYZAddToDoItemViewController 返回瀏覽 XYZToDoListViewController。
通過向目的視圖控制器(要跳轉(zhuǎn)到的視圖控制器)添加操作方法,可以創(chuàng)建 unwind 過渡??梢蕴D(zhuǎn)到的方法必須返回一個(gè)操作 (IBAction),并且在串聯(lián)圖過渡 (UIStoryboardSegue) 中作為參數(shù)采用。您可能想跳轉(zhuǎn)回 XYZToDoListViewController,因此需要將帶有該格式的操作方法添加到 XYZToDoListViewController 界面并進(jìn)行實(shí)現(xiàn)。
(IBAction)unwindToList:(UIStoryboardSegue *)segue;
- (IBAction)unwindToList:(UIStoryboardSegue *)segue
{
}
您可以給跳轉(zhuǎn)操作隨意命名??梢詫⑺麨?unwindToList:,讓跳轉(zhuǎn)操作返回的位置一目了然。對(duì)于今后的項(xiàng)目,可以采用類似的命名慣例,即操作的名稱能清楚表示跳轉(zhuǎn)操作將返回的位置。
當(dāng)前項(xiàng)目中,請(qǐng)將此方法實(shí)現(xiàn)留空。稍后,您將使用此方法從 XYZAddToDoItemViewController 中取回?cái)?shù)據(jù),以將項(xiàng)目添加到待辦事項(xiàng)列表。
若要?jiǎng)?chuàng)建 unwind 過渡,請(qǐng)通過源視圖控制器 XYZAddToDoItemViewController 場(chǎng)景臺(tái)中的“Exit”圖標(biāo),將“Cancel”和“Done”按鈕鏈接到 unwindToList: 操作。
如果您在場(chǎng)景臺(tái)中看到的是場(chǎng)景的描述,而不是“Exit”項(xiàng),請(qǐng)點(diǎn)按畫布上的“放大”image: ../Art/zoom_in_2x.png 按鈕,直到看到該項(xiàng)為止。
一個(gè)菜單將出現(xiàn)在拖移停止的位置。
這是您剛才添加到 XYZToDoListViewController.m 文件的操作。表示當(dāng)輕按“Cancel”按鈕時(shí),將跳轉(zhuǎn)過渡并調(diào)用此方法。
在畫布上,按住 Control 鍵從“Done”按鈕拖到 XYZAddToDoItemViewController 場(chǎng)景臺(tái)中的“Exit”項(xiàng)。
請(qǐng)注意,“Cancel”和“Done”按鈕使用了相同的操作。在下個(gè)教程中,您將在編寫處理 unwind 過渡的代碼時(shí)區(qū)分這兩種情況。
檢查點(diǎn):現(xiàn)在,請(qǐng)運(yùn)行應(yīng)用程序。啟動(dòng)時(shí),您將看到表格視圖,但其中不含數(shù)據(jù)。您可以點(diǎn)按添加按鈕,從 XYZToDoListViewController 瀏覽到 XYZAddToDoItemViewController。也可以點(diǎn)按“Cancel”和“Done”按鈕返回瀏覽表格視圖。
那為什么顯示不了數(shù)據(jù)呢?表格視圖有兩種獲取數(shù)據(jù)的方式,即靜態(tài)獲取或動(dòng)態(tài)獲取。當(dāng)表格視圖的控制器實(shí)現(xiàn)所要求的 UITableViewDataSource 方法時(shí),表格視圖將向其視圖控制器請(qǐng)求數(shù)據(jù)以進(jìn)行顯示,不管 Interface Builder 中是否配置了靜態(tài)數(shù)據(jù)。如果您留意下 XYZToDoListViewController.m,就會(huì)發(fā)現(xiàn)它實(shí)現(xiàn)了三種方法:numberOfSectionsInTableView:, tableView:numberOfRowsInSection:以及 tableView:cellForRowAtIndexPath:。您可以通過注釋掉這些方法的實(shí)現(xiàn),在表格視圖中再次顯示靜態(tài)數(shù)據(jù)。如果感興趣,您可以繼續(xù)試試。
現(xiàn)在,您已經(jīng)完成了應(yīng)用程序界面的開發(fā)工作?,F(xiàn)在有兩個(gè)場(chǎng)景:一個(gè)用于給待辦事項(xiàng)列表添加項(xiàng)目,另一個(gè)用于查看該列表;并且您可以在兩個(gè)場(chǎng)景之間瀏覽。接下來要實(shí)現(xiàn)的功能,是讓用戶添加新的待辦事項(xiàng),并使其顯示在列表中。下一部分講述了如何處理數(shù)據(jù)以實(shí)現(xiàn)該行為。
更多建議: