本教程以第二個教程(「教程:串聯圖」)中建立的項目爲基礎。您將用到從使用設計模式、使用 Foundation 以及編寫自定類中學到的知識,在 ToDoList 應用程序中添加對動態數據的支持。 html
本教程講述瞭如下操做: ios
使用常見的 Foundation 類 設計模式
建立自定數據類 api
實現委託和數據源協議 數組
在視圖控制器之間傳遞數據 app
完成本教程中的全部步驟後,您的應用程序外觀大體是這樣的: 框架
如今就開始吧,請在 Xcode 中打開您的現有項目。 編輯器
目前,使用串聯圖的 ToDoList 應用程序有一個界面和一個導航方案。如今,是時候使用模型對象來添加數據儲存和行爲了。 ide
應用程序的目標在於建立一個待辦事項列表,所以首先您將建立一個自定類XYZToDoItem來表示單個待辦事項。您應該記得,XYZToDoItem類已經在編寫自定類中討論過。 模塊化
建立 XYZToDoItem 類
選取「File」>「New」>「File」(或按下 Command-N)。
這時將會出現一個對話框,提示您爲新文件選取模板。
從左側的 iOS 下方選擇「Cocoa Touch」。
選擇「Objective-C Class」,並點按「Next」。
在「Class」欄中,在XYZ前綴後鍵入ToDoItem。
從「Subclass of」彈出式菜單中選取「NSObject」。
若是您徹底按照本教程操做,那麼在這個步驟以前,「Class」標題多是XYZToDoItemViewController。選取 NSObject 做爲「Subclass of」後,Xcode 會知道您建立了一個正常的自定類,並移除了它先前添加的ViewController文本。
點按「Next」。
存儲位置默認爲您的項目目錄。此處無需更改。
「Group」選項默認爲您的應用程序名稱「ToDoList」。此處無需更改。
「Targets」部分默認選定您的應用程序,未選定應用程序的測試。好極了,這些都無需更改。
點按「Create」。
XYZToDoItem類很容易實現。它具備項目名稱、建立日期,以及該項目是否已完成等屬性。繼續將這些屬性添加到XYZToDoItem類接口。
配置 XYZToDoItem 類
在項目導航器中,選擇XYZToDoItem.h。
將如下屬性添加到該接口,使聲明以下所示:
檢查點:經過選取「Product」>「Build」(或按下 Command-B)來生成項目。儘管該新類還沒有實現任何功能,可是生成它有助於編譯器驗證任何拼寫錯誤。若是發現錯誤,請及時修正:通讀編輯器提供的警 告或錯誤,而後回顧本教程中的說明,確保全部內容與此處的描述相符。
您如今有一個類,能夠用它做爲基礎來爲單個列表項目建立並儲存數據。您還須要保留一個項目列表。在XYZToDoListViewController類中跟蹤此內容較爲合適,視圖控制器負責協調模型和視圖,因此須要對模型進行引用。
Foundation 框架有一個NSMutableArray類,很適合跟蹤項目列表。此處必須使用可變數組,這樣用戶就能夠將項目添加到數組。由於不可變數組NSArray在其初始化後將不容許添加項目。
要使用數組,您須要聲明並建立它。能夠經過分配並初始化數組來完成。
要分配並初始化數組
在項目導航器中,選擇XYZToDoListViewController.m。
因爲項目數組是表格視圖控制器的實現細節,因此應該在 .m 文件中進行聲明,而不是 .h 文件。此操做可以讓項目數組成爲您自定類的私有數組。
將如下屬性添加到接口類別中,它是由 Xcode 在您的自定表格視圖控制器類中建立的。聲明應該是這樣的:
在viewDidLoad方法中分配並初始化toDoItems數組:
viewDidLoad的實際代碼中有一些附加行被註釋掉了,那些行是 Xcode 建立XYZListViewController時插入的。保留與否都沒有影響。
如今,您已經擁有了一個能夠添加項目的數組。添加項目將在單獨的方法loadInitialData中進行,並將經過viewDidLoad調用該方法。因爲此代碼是一個模塊化任務,因此會進入其自身的方法中。固然您也能夠將方法分離出來,從而提升代碼的可讀性。在真正的應用程序中,此方法可 能會從某種永久儲存形式載入數據,例如文件。如今,咱們的目標是瞭解表格視圖如何處理自定數據項目,那麼讓咱們建立一些測試數據來體驗一下吧。
以建立數組的方式建立項目:分配並初始化。而後,給項目命名。該名稱將顯示在表格視圖中。按照此方法建立一組項目。
載入初始數據
在@implementation行下方,添加一個新方法loadInitialData。
在此方法中,建立幾個列表項目,並將它們添加到數組。
在viewDidLoad方法中調用loadInitialData。
檢查點:經過選取「Product」>「Build」來生成項目。您應該會在loadInitialData方法的代碼行上看到大量錯誤。第一行是出錯的關鍵所在,錯誤提示應該是「Use of undeclared identifier XYZToDoItem」。這說明編譯器在編譯XYZToDoListViewController時不知道XYZToDoItem。編譯器比較特別,您須要明確告知它應當注意什麼。
讓編譯器注意您的自定列表項目類
在XYZToDoListViewController.m文件的頂部附近找到#import "XYZToDoListViewController.h"行。
緊接着在其下方添加如下行:
檢查點:經過選取「Product」>「Build」來生成項目。項目生成時應該沒有錯誤。
目前,表格視圖具備一個可變數組,預填充了幾個示例待辦事項。如今您須要在表格視圖中顯示數據。
經過讓XYZToDoListViewController成爲表格視圖的數據源,能夠實現這一點。不管要讓什麼成爲表格視圖的數據源,都須要實施UITableViewDataSource協議。須要實施的方法正是您在第二個教程中註釋掉的那些。建立有效的表格視圖須要三個方法。第一個方法是numberOfSectionsInTableView:,它告訴表格視圖要顯示幾個部分。對於此應用程序,表格視圖只須要顯示一個部分,因此實現比較簡單。
在表格中顯示一個部分
在項目導航器中,選擇XYZToDoListViewController.m。
若是您在第二個教程中註釋掉了表格視圖數據源方法,如今請移除那些註釋標記。
模板實現的部分以下所示。
您想要單個部分,因此須要移除警告行並將返回值由 0 更改成 1。
更改numberOfSectionsInTableView:數據源方法以便返回單個部分,像這樣:
下一個方法tableView:numberOfRowsInSection:告訴表格視圖要在給定部分中顯示幾行。如今表格中有一個部分,而且每一個待辦事項在表格視圖中都應該有它本身的行。這意味着行數應該等於toDoItems數組中的XYZToDoItem對象數。
返回表格中的行數
在項目導航器中,選擇XYZToDoListViewController.m。
您可看到模板實現的部分是這樣的:
您想要返回所擁有的列表項目的數量。幸運的是,NSArray有一個很方便的方法,稱爲count,它會返回數組中的項目數,所以行數是[self.toDoItems count]。
更改tableView:numberOfRowsInSection:數據源方法,使其返回正確的行數。
最後一個方法,tableView:cellForRowAtIndexPath:請求一個單元格來顯示給定行。到如今爲止,您只是處理了代碼,可是界面的絕大部分是針對行顯示的單元格。幸運的是,Xcode 可以讓您輕鬆地在 Interface Builder 中設計自定單元格。首個任務是設計您的單元格,並告訴表格視圖不要使用靜態內容,而要使用具備動態內容的原型單元格。
配置表格視圖
打開串聯圖。
在大綱中選擇表格視圖。
選定表格視圖後,在實用工具區域中打開「Attributes」檢查器 。
在「Attributes」檢查器中,將表格視圖的「Content」屬性從「Static Cells」更改成「Dynamic Prototypes」。
Interface Builder 會採用您配置的靜態單元格,並將它們所有轉換爲原型。原型單元格,顧名思義,是使用您要顯示的文本樣式、顏色、圖像或其餘屬性進行配置,並在運行時從數據 源獲取其數據的單元格。數據源會爲每一行載入一個原型單元格,而後配置該單元格來顯示該行的數據。
要載入正確的單元格,數據源須要知道單元格的名稱,而且該名稱也必須在串聯圖中進行配置。
設定原型單元格名稱時,也將配置另外一個屬性—單元格選擇樣式,該樣式用於肯定用戶輕按單元格時單元格的外觀。將單元格選擇樣式設定爲「None」,使用戶 輕按單元格時單元格不會高亮顯示。這是當用戶輕按待辦事項列表中的項目,將其標記爲已完成或未完成時,您想要單元格呈現的行爲。稍後會在本教程中實現該功 能。
配置原型單元格
在表格中選擇第一個表格視圖單元格。
在「Attributes」檢查器中,找到「Identifier」欄並鍵入ListPrototypeCell。
在「Attributes」檢查器中,找到「Selection」欄並選取「None」。
您也能夠更改原型單元格的字體或其餘屬性。基本配置很容易完成,您能夠輕鬆記下。
下一步是實現tableView:cellForRowAtIndexPath:方法,讓數據源爲給定行配置單元格。表格視圖在想要顯示給定行時會調用此數據源方法。對於行數較少的表格視圖,全部行可能會同時出如今屏幕上,因此表格中 的每一行都會調用此方法。可是,行數不少的表格視圖在給定時間內只會顯示所有項目中的一小部分。最有效的方式是讓表格視圖僅請求要顯示行的單元格,而這一 點可經過tableView:cellForRowAtIndexPath:讓表格視圖實現。
對於表格中的任何給定行,取回toDoItems數組中的相應條目,而後將單元格的文本標籤設定爲項目的名稱。
在表格中顯示單元格
在項目導航器中,選擇XYZToDoListViewController.m。
找到tableView:cellForRowAtIndexPath:數據源方法。模板實現是這樣的:
該模板執行多個任務。它會建立一個變量來保存單元格的標識符,向表格視圖請求具備該標識符的單元格,添加一個註釋註明配置該單元格的代碼應該寫在哪裏,而後返回該單元格。
要讓此代碼爲您的應用程序所用,須要將標識符更改成您在串聯圖中設定的標識符,而後添加代碼來配置該單元格。
將單元格標識符更改成您在串聯圖中設定的標識符。爲了不拼寫錯誤,請將串聯圖中的標識符拷貝並粘貼到實現文件中。該單元格標識符行如今應該是這樣的:
在 return 語句前,添加如下代碼行:
您的tableView:cellForRowAtIndexPath:方法應以下圖所示:
檢查點:運行您的應用程序。您在loadInitialData中添加的項目列表應該在表格視圖中顯示爲單元格。
若是沒法將待辦事項列表中的項目標記爲已完成,那麼這個待辦事項列表還不夠好。如今,讓咱們來添加這樣的支持。一個簡單的界面應該能夠在用戶輕按單元格時 切換完成狀態,並在已完成的項目旁邊顯示勾號。幸運的是,表格視圖附帶了一些內建行爲,您能夠利用這些行爲來實現這樣的簡單界面。須要注意的是,在用戶輕 按單元格時,表格視圖要通知它們的委託。因此咱們的任務是寫一段代碼,對用戶輕按表格中的待辦事項這個操做做出響應。
您在串聯圖中配置XYZToDoListViewController時,Xcode 就已經讓它成爲表格視圖的委託了。您要作的只是實現tableView:didSelectRowAtIndexPath:委託方法,使其響應用戶輕按,並在適當時候更新您的待辦事項列表。
選定單元格後,表格視圖會調用tableView:didSelectRowAtIndexPath:委託方法,來查看它應如何處理選擇操做。在此方法中,您須要編寫代碼來更新待辦項目的完成狀態。
將項目標記爲已完成或未完成
在項目導航器中,選擇XYZToDoListViewController.m。
將如下代碼行添加到文件末尾,在@end行正上方:
請試着鍵入第二行,而不是拷貝和粘貼。您將發現代碼補全是 Xcode 最節省時間的功能之一。當 Xcode 顯示出可能的補全建議列表時,請滾動瀏覽列表,找到想要的建議,而後按下 Return 鍵。Xcode 會爲您插入整行。
您想要響應輕按,但並不想讓單元格保持選定狀態。添加如下代碼,讓單元格在選定後當即取消選定:
在toDoItems數組中搜索相應的XYZToDoItem。
切換被輕按項目的完成狀態。
告訴表格視圖從新載入您剛更新過數據的行。
您的tableView:didSelectRowAtIndexPath:方法應以下圖所示:
檢查點:運行您的應用程序。您在loadInitialData中添加的項目列表在表格視圖中顯示爲單元格。但當您輕按項目時,並無任何反應。爲何呢?
緣由是您還沒有配置顯示項目完成狀態的表格視圖單元格。要實現此功能,您須要回到tableView:cellForRowAtIndexPath:方法,並配置單元格以在項目完成時顯示指示。
指示項目已完成的一種方式是在其旁邊放置一個勾號。幸運的是,表格視圖右邊能夠有一個單元格附屬物。默認狀況下,單元格中沒有任何附屬物;不過您能夠進行更改,使其顯示不一樣的附屬物。其中的一個附屬物就是勾號。您要作的是根據待辦事項的完成狀態,設定單元格的附屬物。
顯示項目的完成狀態
前往tableView:cellForRowAtIndexPath:方法。
在設定單元格的文本標籤的代碼行下方添加如下代碼:
您的tableView:cellForRowAtIndexPath:方法如今應以下圖所示:
檢查點:運行應用程序。您在loadInitialData中添加的項目列表在表格視圖中顯示爲單元格。輕按項目時,其旁邊應該出現一個勾號。若是您再次輕按同一項目,勾號會消失。
構建待辦事項列表應用程序功能的最後一步是實現添加項目的能力。當用戶在XYZAddToDoItemViewController場景的文本欄中輸入項目名稱,並輕按「Done」按鈕時,您想要視圖控制器建立一個新的列表項目並將其傳遞迴XYZToDoListViewController,以顯示在待辦事項列表中。
首先,您須要擁有一個列表項目來進行配置。就像表格視圖那樣,視圖控制器是將界面鏈接到模型的邏輯位置。爲XYZAddToDoItemViewController添加一個屬性來保存新的待辦事項。
將 XYZToDoItem 添加到 XYZAddToDoItemViewController 類
在項目導航器中,選擇XYZAddToDoItemViewController.h。
因爲稍後須要從表格視圖控制器訪問列表項目,因此務必將其設爲公共屬性。這就是爲何要在接口文件XYZAddToDoItemViewController.h中聲明它,而不在實現文件XYZAddToDoItemViewController.m中聲明的緣由所在。
將 import 聲明添加到@interface行上方的XYZToDoItem類中。
將toDoItem屬性添加到該接口。
要得到新項目的名稱,視圖控制器須要訪問用戶輸入名稱的文本欄。要實現此功能,請建立從XYZAddToDoItemViewController類到串聯圖中的文本欄的鏈接。
將文本欄鏈接到視圖控制器
在大綱視圖中,選擇XYZAddToDoItemViewController對象。
點按窗口工具欄右上角的「Assistant」按鈕,打開輔助編輯器。
右邊的編輯器出現時,應該顯示有XYZAddToDoItemViewController.m。若是未顯示,請點按右邊的編輯器中的文件名,並選取XYZAddToDoItemViewController.m。
輔助編輯器可以讓您一次打開兩個文件,以便可以在它們之間執行操做。例如,在源文件中鍵入一個屬性,而源文件的對象又在接口文件中。
在串聯圖中選擇文本欄。
按住 Control 鍵從畫布上的文本欄拖到右邊編輯器中的代碼顯示窗口,到達XYZAddToDoItemViewController.m中的@interface行正下方時中止拖移。
在出現的對話框中,爲「Name」欄鍵入「textField」。
讓選項的其他部分保持不變。您的對話框應以下圖所示:
點按「Connect」。
Xcode 會將必要的代碼添加到XYZAddToDoItemViewController.m,用於儲存指向文本欄的指針,並配置串聯圖來設置該鏈接。
另外,您須要知道什麼時候建立項目。若是想要僅在「Done」按鈕被輕按時才建立項目,那麼請將「Done」按鈕添加爲 Outlet。
將「Done」按鈕鏈接到視圖控制器
在串聯圖中,打開輔助編輯器,將最右邊的窗口設定爲XYZAddToDoItemViewController.m。
在串聯圖中選擇「Done」按鈕。
按住 Control 鍵從畫布上的「Done」按鈕拖到右邊的編輯器中的代碼顯示窗口,到達XYZAddToDoItemViewController.m中的textField屬性正下方的行時中止拖移。
在出現的對話框中,在「Name」欄鍵入「doneButton」。
保持選項的其他部分不變。對話框應以下圖所示:
點按「Connect」。
您如今有了識別「Done」按鈕的方式。因爲想在輕按「Done」按鈕時建立一個項目,因此須要知道該按鈕什麼時候被按下。
當用戶輕按「Done」按鈕時,它會啓動一個 unwind segue,返回到待辦事項列表,這正是您在第二個教程中配置的接口。在 segue 執行前,系統經過調用prepareForSegue:,給所包含的視圖控制器一次準備機會。這即是檢查用戶是否輕按了「Done」按鈕的時候。若是是,將會建立一個新的待辦事項。您能夠檢查輕按了哪個按鈕,若是是「Done」按鈕,將會建立項目。
輕按「Done」按鈕後建立項目
在項目導航器中選擇XYZAddToDoItemViewController.m。
在@implementation行下方添加prepareForSegue:方法:
在此方法中,請查看「Done」按鈕是否按下。
若是未按下就不存儲項目,而是讓方法返回但不執行任何其餘操做。
查看一下文本欄中是否有文本。
若是有文本,將會建立一個新項目,並用文本欄中的文本爲其命名。另外,請確保完成狀態被設定爲「NOfalse」。
若是沒有文本,您就不須要存儲項目,也不須要執行任何其餘操做。
您的prepareForSegue:方法應以下圖所示:
既然建立了一個新項目,那麼就須要將該項目傳遞迴XYZToDoListViewController,以便它能夠將項目添加到待辦事項列表。要完成此功能,請從新訪問您在第二個教程中編寫的unwindToList:方法。當用戶輕按「Cancel」或「Done」按鈕,XYZAddToDoItemViewController場景會在關閉時調用該方法。
就像做爲 unwind segue 目標的全部方法同樣,unwindToList:方法也採用 segue 做爲參數。segue 參數是從XYZAddToDoItemViewController展開並返回到XYZToDoListViewController的過渡。因爲 segue 是兩個視圖控制器之間的過渡,因此知道它的源視圖控制器是XYZAddToDoItemViewController。經過向 segue 對象請求其源視圖控制器,您能夠用unwindToList:方法訪問儲存在源視圖控制器中的任何數據。目前,您想要訪問toDoItem。若是它是nil,則該項目並未建立。緣由多是文本欄沒有文本,或者是用戶輕按了「Cancel」按鈕。若是toDoItem有值,則能夠取回該項目,再添加到toDoItems數組,並經過從新載入表格視圖中的數據將其顯示在待辦事項列表中。
儲存並顯示新項目
在項目導航器中,選擇XYZToDoListViewController.m。
將 import 聲明添加到@interface行上方的XYZAddToDoItemViewController類中。
找到您在第二個教程中添加的unwindToList:方法。
在此方法中,取回源視圖控制器XYZAddToDoItemViewController,即您要展開的控制器。
取回控制器的待辦事項。
這就是輕按「Done」按鈕時建立的項目。
看看這個項目是否存在。
若是是nil,多是「Cancel」按鈕關閉了屏幕,或者是文本欄中沒有文本,所以沒必要存儲該項目。
若是項目存在,請添加到toDoItems數組。
從新載入表格中的數據。
由於表格視圖不會跟蹤其數據,因此數據源(在這個程序中是表格視圖控制器)有責任通知表格視圖什麼時候有新數據供其顯示。
您的unwindToList:方法應以下圖所示:
檢查點:運行您的應用程序。如今,當您點按添加按鈕 (+) 並建立一個新項目時,它應該會顯示在待辦事項列表中。恭喜您!您已經建立了一個應用程序,它能接收用戶的輸入,將其儲存在對象中,並在兩個視圖控制器之間傳遞該對象。對於基於串聯圖的應用程序,這是在場景之間移動數據的基礎。
您差很少完成了開發 iOS 應用程序的入門之旅。最後一部分更詳細地講述瞭如何查詢文稿材料,而且爲您學習建立更高級的應用程序給出了一些後續建議。