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