上一篇 使用 UITableView 創建表格應用演練(2)——從plist文件加載並顯示數據" 完成后,“微博關注人”這個應用雖然距離最終的完成還有不小的距離,但從視覺上已經比演練(1)完成時有了不小的改進。:]
細心的朋友們在上次演練中已經發現,我們定義的數據結構中,有一個名為“類別”的字段,這個字段的設置主要用於幫助我們更好地管理我們的關注對象。本文演練僅僅涉及一個問題,就是如何按照“類別”在表格中分區段顯示數據。本此演練之后,相信您會對iOS中的數組(NSMutableArray)和plist文件的使用也會有一個新的理解。
一. 開始之前
開始之前,我們需要簡單回顧一下上一次的一些內容,這樣便於我們演練的開始。
1. 在FocusUsers.plist文件中順序存放所有關注用戶的數據;
2. 我們定義了一個名為JOYFocusUser的類來存放每個用戶的信息;
3. 我們在視圖控制器中用到了一個NSMutableArray數組存放plist文件內容,並通過JOYFocusUser類做為映射,便於程序編寫過程中的訪問。
那么現在問題出來了——從plist文件中加載過來的數據是一個序列的,而分區段顯示數據時,單一序列的數組顯然有些難以勝任,這個時候我們需要做一個中轉。如下圖所示:
如果我們從上一講中的單一序列,變成有圖所示的二維序列問題似乎就好解決了。:]
好,思路有了,現在讓我們馬上動手。
二. 數據調整
1. 在導航區域,點擊“FocusUsers.plist”文件,打開我們上次演練中建立的plist文件;
2. 在“FocusUsers.plist”上點擊鼠標右鍵,選擇“Open As”“Source Code”,並使用下列代碼替換我們上次使用的plist內容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 <plist version="1.0"> 4 <array> 5 <array> 6 <dict> 7 <key>UserName</key> 8 <string>愛Apps</string> 9 <key>Image</key> 10 <string>愛Apps.jpeg</string> 11 <key>WebSite</key> 12 <string>http://weibo.com/iapps</string> 13 <key>Favorite</key> 14 <real>3.5</real> 15 <key>Category</key> 16 <string>蘋果咨詢</string> 17 </dict> 18 <dict> 19 <key>UserName</key> 20 <string>蘋果匯</string> 21 <key>Image</key> 22 <string>蘋果匯.jpeg</string> 23 <key>WebSite</key> 24 <string>http://weibo.com/appleus</string> 25 <key>Favorite</key> 26 <real>3.5</real> 27 <key>Category</key> 28 <string>蘋果咨詢</string> 29 </dict> 30 <dict> 31 <key>UserName</key> 32 <string>數碼iPhone大百科</string> 33 <key>Image</key> 34 <string>數碼iPhone大百科.jpeg</string> 35 <key>WebSite</key> 36 <string>http://weibo.com/gx110</string> 37 <key>Favorite</key> 38 <real>3.5</real> 39 <key>Category</key> 40 <string>蘋果咨詢</string> 41 </dict> 42 </array> 43 <array> 44 <dict> 45 <key>UserName</key> 46 <string>新浪視野</string> 47 <key>Image</key> 48 <string>新浪視野.jpeg</string> 49 <key>WebSite</key> 50 <string>http://weibo.com/wboard</string> 51 <key>Favorite</key> 52 <real>3.5</real> 53 <key>Category</key> 54 <string>官方機構</string> 55 </dict> 56 </array> 57 <array> 58 <dict> 59 <key>UserName</key> 60 <string>李開復</string> 61 <key>Image</key> 62 <string>李開復.jpeg</string> 63 <key>WebSite</key> 64 <string>http://weibo.com/kaifulee</string> 65 <key>Favorite</key> 66 <real>3.5</real> 67 <key>Category</key> 68 <string>IT名人</string> 69 </dict> 70 </array> 71 </array> 72 </plist>
對比上一次演練中我們使用的plist文件,我們多引入了一層array定義,這樣就把原有的一維數據序列,調整成二維序列了。怎么樣?還不錯吧。:]
三. 數據加載處理
1. 在導航區域,點擊打開“JOYTableViewController.m”文件;
2. 在接口定義中將原來定義的數據名稱由_userList改為_categoryList,如下所示:
1 @interface JOYTableViewController () { 2 @private 3 NSMutableArray *_categoryList; 4 }
3. 在viewDidLoad方法中調整數據加載部分進行調整,調整后的viewDidLoad方法如下所示:
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 // 設定pList文件路徑 6 NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"FocusUsers.plist" ofType:nil]; 7 // 填充數組內容 8 NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:dataPath]; 9 10 _categoryList = [[NSMutableArray alloc]init]; 11 for (NSDictionary *item in array) { 12 NSMutableArray *userList = [[NSMutableArray alloc]init]; 13 14 // 針對每個分類項,創建一個用戶數組 15 for (NSDictionary *users in item) { 16 JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:users]; 17 [userList addObject:user]; 18 } 19 20 // 將用戶數組項目添加到分類數組中 21 [_categoryList addObject:userList]; 22 } 23 }
4. 找到numberOfSectionsInTableView方法,將其中代碼進行修改,如下所示:
1 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 2 { 3 return [_categoryList count]; 4 }
在本演練數據中,我們一共包含三個分類,所以在此返回結果是3。
5. 找到
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
方法,將其中代碼進行修改,如下所示:
1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 2 { 3 return [[_categoryList objectAtIndex:section]count]; 4 }
這里的代碼稍微有些別扭,我們會在后續調整一下,讓它更好讀一些,在此先簡單解釋一下。
從plist文件的結構中,我們不難發現[_categoryList objectAtIndex:section]對應的是指定區段數的一個用戶數組,假如我們把這個理解為“userList”,則這條語句可以看成是return [userList count],返回的是指定區段的用戶數組的個數。
6. 找到
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法,將其中解析數據部分代碼進行修改,修改后的方法如下所示:
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3 static NSString *CellIdentifier = @"Cell"; 4 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 5 6 // Configure the cell... 7 // 實例化單元格對象 8 if (cell == nil) { 9 cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 10 } 11 12 NSMutableArray *array = [_categoryList objectAtIndex:[indexPath section]]; 13 JOYFocusUser *user = [array objectAtIndex:[indexPath row]]; 14 15 // 設置單元格文本 16 // NSDictionary *item = [_userList objectAtIndex:indexPath.row]; 17 [cell.textLabel setText:[user userName]]; 18 // 設定字體 19 [cell.textLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0f]]; 20 // 改變字體顏色 21 [cell.textLabel setTextColor:[UIColor orangeColor]]; 22 // 調整文本居中對齊 23 [cell.textLabel setTextAlignment:UITextAlignmentCenter]; 24 25 // 顯示頭像 26 [cell.imageView setImage:[user image]]; 27 28 return cell; 29 }
為了便於大家的閱讀,我把上一次演練中的代碼注釋了,這樣方便我們更加直觀地看出到底做了哪些修改。
7. 運行一下,看看效果:]
天啊,忙乎了一溜夠,竟然和上次演練之后沒有發生任何的變化,這⋯⋯
不要着急,現在激動人心的時刻就要到了,嘿嘿。
8. 找到numberOfSectionsInTableView方法,在它的下面插入一個
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 方法
並增加一條語句,如下所示:
1 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 2 // 獲取指定區段的用戶數組 3 NSMutableArray *userList = [_categoryList objectAtIndex:section]; 4 // 獲取數組中第一個用戶記錄 5 JOYFocusUser *user = [userList objectAtIndex:0]; 6 // 返回該用戶的分類名稱 7 return user.categoryName; 8 }
相關語句到底干了什么,見注釋即可,我就不再啰嗦了。
9. 運行一下,如下圖所示:
哈哈,怎么樣?不復雜吧。
小提示:可能有不少從其他平台,例如Eclipse或者MS VS等轉過來的朋友會向我當初一樣有一些類似的疑問:這個方法是怎么加入的呢?我怎么知道系統預設了這個方法呢?有沒有某個菜單命令能夠彈出一個對話框,讓我選擇具體要重載哪個方法呢?
答案是:直接輸入。呵呵,剛開始使用Xcode時,我也有些不習慣,不過后來發現,Xcode提供的智能輸入提示非常友好,在程序開發時非常高效地,程序員不用時不時地因為一些小事,就不得不把手從鍵盤移到鼠標上,去做一些無聊的事情。在Xcode中,編寫某一個類的代碼時,幾乎可以不用使用鼠標,就完成所有的編碼工作。
好了,言歸正傳,在上述的代碼中,某些地方有些取巧,如果你只是開發這么一個簡單的應用,已經足夠了。不過如果考慮到以后系統的維護和擴充,我們還是要盡量將數據和界面分開。
四. 使用分類數據模型
1. 在導航區域,點擊並打開“JOYFocusUser.h”文件,在文件末尾增加如下代碼:
1 @interface JOYCategory : NSObject 2 3 @property (strong, nonatomic) NSString *categoryName; 4 @property (strong, nonatomic) NSMutableArray *userList; 5 6 // 使用用戶列表實例化對象 7 - (id)initWithArray:(NSMutableArray *)userList; 8 9 @end
在此,我們新定義了一個JOYCategory的類,用於按類別存儲用戶列表;
2. 點擊打開“JOYFocusUser.m”文件,在文件的末尾增加如下代碼:
1 @implementation JOYCategory 2 @synthesize categoryName = _categoryName; 3 @synthesize userList = _userList; 4 5 - (id)initWithArray:(NSMutableArray *)userList { 6 7 self = [super init]; 8 if (self) { 9 NSMutableArray *list = [[NSMutableArray alloc]init]; 10 for (NSDictionary *item in userList) { 11 JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:item]; 12 [list addObject:user]; 13 } 14 15 JOYFocusUser *user = [list objectAtIndex:0]; 16 _categoryName = user.categoryName; 17 _userList = list; 18 } 19 return self; 20 } 21 22 @end
3. 在導航區域,點擊打開“JOYTableViewController.m”文件;
4. 對viewDidLoad中的數據加載部分的代碼調整如下:
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 // 設定pList文件路徑 6 NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"FocusUsers.plist" ofType:nil]; 7 // 填充數組內容 8 NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:dataPath]; 9 10 _categoryList = [[NSMutableArray alloc]init]; 11 // for (NSDictionary *item in array) { 12 // NSMutableArray *userList = [[NSMutableArray alloc]init]; 13 // 14 // // 針對每個分類項,創建一個用戶數組 15 // for (NSDictionary *users in item) { 16 // JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:users]; 17 // [userList addObject:user]; 18 // } 19 // 20 // // 將用戶數組項目添加到分類數組中 21 // [_categoryList addObject:userList]; 22 // } 23 for (NSMutableArray *item in array) { 24 JOYCategory *category = [[JOYCategory alloc]initWithArray:item]; 25 [_categoryList addObject:category]; 26 } 27 }
5. 在
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section方法中做如下調整:
1 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 2 // // 獲取指定區段的用戶數組 3 // NSMutableArray *userList = [_categoryList objectAtIndex:section]; 4 // // 獲取數組中第一個用戶記錄 5 // JOYFocusUser *user = [userList objectAtIndex:0]; 6 // // 返回該用戶的分類名稱 7 // return user.categoryName; 8 JOYCategory *category = [_categoryList objectAtIndex:section]; 9 return [category categoryName]; 10 }
6. 在
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section方法中做如下調整:
1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 2 { 3 // return [[_categoryList objectAtIndex:section]count]; 4 JOYCategory *category = [_categoryList objectAtIndex:section]; 5 return [category.userList count]; 6 }
7. 在
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中做如下調整:
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3 static NSString *CellIdentifier = @"Cell"; 4 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 5 6 // Configure the cell... 7 // 實例化單元格對象 8 if (cell == nil) { 9 cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 10 } 11 12 // NSMutableArray *array = [_categoryList objectAtIndex:[indexPath section]]; 13 // JOYFocusUser *user = [array objectAtIndex:[indexPath row]]; 14 JOYCategory *category = [_categoryList objectAtIndex:[indexPath section]]; 15 JOYFocusUser *user = [category.userList objectAtIndex:[indexPath row]]; 16 17 // 設置單元格文本 18 // NSDictionary *item = [_userList objectAtIndex:indexPath.row]; 19 [cell.textLabel setText:[user userName]]; 20 // 設定字體 21 [cell.textLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0f]]; 22 // 改變字體顏色 23 [cell.textLabel setTextColor:[UIColor orangeColor]]; 24 // 調整文本居中對齊 25 [cell.textLabel setTextAlignment:UITextAlignmentCenter]; 26 27 // 顯示頭像 28 [cell.imageView setImage:[user image]]; 29 30 return cell; 31 }
小提示:為了便於大家的閱讀,我把前面演練中的代碼注釋了,這樣方便我們更加直觀地看出到底做了哪些修改。由於我把每一個方法的完成代碼都復制過來了,其實我們在每個方法中所作的修改只是一兩條語句而已。
8. 運行看一下效果,和前面演練完的效果並沒有太大的變化,不過現在的代碼的可讀性已經有所提高了:]
五. 小結
首先要向大家表示歉意,因為本人的博客只是利用業余時間編寫的,更新速度有些緩慢,還望大家見諒。
本演練源程序下載地址:JoyiOSMyFocus3.zip
到目前位置,我們對UITableView的數據加載、顯示、分組已經做了一個初步的介紹。在后面的演練中,我們將針對自定義單元格、表格數據操作以及自定義視圖進行介紹,同時引入一個iOS應用中非常常見的Navigation控件。計划還需要兩~三章的內容可以完成,敬請期待。