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