本篇學習目標:
1. 學習使用讀取plist
2. UITableView 分組顯示數據
3. UITableView 加上搜索功能
不‘費’話,直接跟我一起來,進行如下操作:
1. 創建項目,在此略過,可以參考前篇文章,在此只顯示一個項目的圖:
2. 添加plist 文件
PS: plist文件是什么呢? 它全名是:Property List,屬性列表文件,它是一種用來存儲串行化后的對象的文件。屬性列表文件的擴展名為.plist,因此通常被稱為plist文件。文件是xml格式 的。Plist文件通常用於儲存用戶設置,也可以用於存儲捆綁的信息。
data.plist 文件圖片如下:
查看源代碼,如下

<! DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" >
< plist version ="1.0" >
< dict >
< key >1992 </ key >
< array >
< string >漫畫威龍 </ string >
< string >家有喜事 </ string >
< string >逃學威龍2 </ string >
< string >審死官 </ string >
< string >鹿鼎記 </ string >
< string >鹿鼎記2神龍教 </ string >
< string >武狀元蘇乞兒 </ string >
</ array >
< key >1993 </ key >
< array >
< string >唐伯虎點秋香 </ string >
< string >逃學威龍3龍過雞年 </ string >
< string >濟公 </ string >
</ array >
< key >1994 </ key >
< array >
< string >破壞之王 </ string >
< string >九品芝麻官 </ string >
< string >國產凌凌漆 </ string >
</ array >
< key >1995 </ key >
< array >
< string >大話西游之月光寶盒 </ string >
< string >回魂夜 </ string >
< string >百變星君 </ string >
</ array >
< key >1996 </ key >
< array >
< string >大內密探零零發 </ string >
< string >食神 </ string >
</ array >
< key >1997 </ key >
< array >
< string >97家有喜事 </ string >
< string >算死草 </ string >
</ array >
< key >1998 </ key >
< array >
< string >行運一條龍 </ string >
</ array >
< key >1999 </ key >
< array >
< string >喜劇之王 </ string >
< string >千王之王2000 </ string >
</ array >
< key >2000年以后 </ key >
< array >
< string >少林足球 </ string >
< string >功夫 </ string >
< string >長江七號 </ string >
</ array >
< key >1991 </ key >
< array >
< string >整蠱專家 </ string >
< string >龍的傳人 </ string >
< string >新精武門1991 </ string >
< string >逃學威龍 </ string >
< string >賭俠2上海灘賭聖 </ string >
< string >情聖 </ string >
</ array >
</ dict >
</ plist >
3. 刪除默認的ViewController,添加TableViewController(如果不清楚,請查看前篇文章)。
屬性設置如下:
- Style: 顯示風格,上篇我們使用是基本的Basic,這里我們使用Subtitle,簡單的講,就是標題與字幕的顯示。
- Identifier: cell 的身份ID,這個是必須設置,我們這里設置成MovieCell
- Accessory: 詳細內容時的圖標,我們這里設置成Detail Disclosure
4. 添加myDataViewController類,繼承於UITableViewController,先修改 myDataViewController.h 文件
// myDataViewController.h
// listMovieGroup
//
// Created by tony on 12-8-31.
// Copyright (c) 2012年 chinapcc.com. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface myDataViewController : UITableViewController
{
// 電影標題數據字典
NSDictionary *movieTitles;
// 年份的數組
NSArray *years;
}
// 屬性:電影標題數據字典
@property (nonatomic,retain) NSDictionary *movieTitles;
// 屬性:年份的數組
@property (nonatomic,retain) NSArray *years;
@end
5. 修改 myDataViewController.m 文件
添加屬性與加載時的代碼:
@synthesize movieTitles;
- ( void)viewDidLoad
{
// 獲取plist資源文件地址
NSString *path = [[NSBundle mainBundle] pathForResource: @" data " ofType: @" plist "];
// 這是寫入日記,為了調試,不是必須的
NSLog( @" 資源文件路徑: %@ ",path);
// 根據文件路徑獲取字典內容
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.movieTitles = dict;
// 根據字典,獲得年份的數組
NSArray *array = [[movieTitles allKeys] sortedArrayUsingSelector:@selector(compare:)];
self.years = array;
// 原來應該有如下兩句,xcode 4.2以后,啟用ARC之后,就不需要了
// [dict release];
// [array release];
[super viewDidLoad];
}
- ( void)viewDidUnload
{
self.movieTitles = nil;
self.years = nil;
[super viewDidUnload];
}
6. 綁定數據源
{
// 返回節點數,就是顯示幾個組,我們這里是按年份顯示數據
return [years count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// 獲取當前節點的年份
NSString *year = [years objectAtIndex:section];
// 根據節點的年份,獲取字節點的數組
NSArray *movieSection = [movieTitles objectForKey:year];
// 返回當前字節的數量
return [movieSection count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @" MovieCell ";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// 獲取節點的年份
NSString *year = [years objectAtIndex:[indexPath section]];
// 獲取年份內所有電影數組
NSArray *movie = [movieTitles objectForKey:year];
// 根據數組獲取電影的標題
cell.textLabel.text = [movie objectAtIndex:[indexPath row]];
cell.detailTextLabel.text = @" 主演:周星馳 ";
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
// 獲取年份
NSString *year = [years objectAtIndex:section];
return year;
}
7. 不要忘記以下兩個地方需要設置一下:
設置顯示分組風格:
設置與控制器綁定:
8. 恭喜你完成,可以看一看效果
9. 結束了嗎?還沒有,還要有一個搜索,接下來吧。。。添加一個搜索框
10. 修改 myDataViewController.h 文件

// myDataViewController.h
// listMovieGroup
//
// Created by tony on 12-8-31.
// Copyright (c) 2012年 chinapcc.com. All rights reserved.
//
#import <UIKit/UIKit.h>
// 這里要實現一個委托 UISearchBarDelegate
@interface myDataViewController : UITableViewController<UISearchBarDelegate>
{
// 電影標題數據字典
NSDictionary *movieTitles;
// 年份的數組
NSArray *years;
// 這是與搜索框關聯的對像
IBOutlet UISearchBar *searchBar;
// 標識:是否在搜索狀態中
BOOL isSearchOn;
// 標識:是否能選擇行
BOOL canSelectRow;
// 所有電影列表
NSMutableArray *listOfMovies;
// 搜索結果列表
NSMutableArray *searchResult;
}
// 屬性:電影標題數據字典
@property (nonatomic,retain) NSDictionary *movieTitles;
// 屬性:年份的數組
@property (nonatomic,retain) NSArray *years;
// 屬性:搜索框
@property (nonatomic,retain) UISearchBar *searchBar;
// 方法:搜索電影列表
-( void) searchMoviesTableView;
@end
11. 修改 myDataViewController.m 文件 注解在代碼中,請大家仔細看清楚

// myDataViewController.m
// listMovieGroup
//
// Created by tony on 12-8-31.
// Copyright (c) 2012年 chinapcc.com. All rights reserved.
//
#import " myDataViewController.h "
@interface myDataViewController ()
@end
@implementation myDataViewController
@synthesize years;
@synthesize movieTitles;
@synthesize searchBar;
- ( id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- ( void)viewDidLoad
{
// 獲取plist資源文件地址
NSString *path = [[NSBundle mainBundle] pathForResource: @" data " ofType: @" plist "];
// 這是寫入日記,為了調試,不是必須的
NSLog( @" 資源文件路徑: %@ ",path);
// 根據文件路徑獲取字典內容
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.movieTitles = dict;
// 根據字典,獲得年份的數組
NSArray *array = [[movieTitles allKeys] sortedArrayUsingSelector:@selector(compare:)];
self.years = array;
// 原來應該有如下兩句,xcode 4.2以后,啟用ARC之后,就不需要了
// [dict release];
// [array release];
// 設置視圖的搜索框
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeYes;
// 初始化電影列表
listOfMovies = [[NSMutableArray alloc]init];
for(NSString *year in array)
{
NSArray *movies = [movieTitles objectForKey:year];
for (NSString *title in movies) {
[listOfMovies addObject:title];
}
}
// 初始化搜索結果數組
searchResult = [[NSMutableArray alloc] init];
// 設置狀態
isSearchOn = NO;
canSelectRow = YES;
[super viewDidLoad];
}
- ( void)viewDidUnload
{
self.movieTitles = nil;
self.years = nil;
self.searchBar = nil;
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// 返回節點數,就是顯示幾個組,我們這里是按年份顯示數據
if (isSearchOn) {
return 1; // 進入搜索狀態,只有一個節點
} else {
return [years count];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isSearchOn)
{
return [searchResult count]; // 搜索結果的數量
}
else
{
// 獲取當前節點的年份
NSString *year = [years objectAtIndex:section];
// 根據節點的年份,獲取字節點的數組
NSArray *movieSection = [movieTitles objectForKey:year];
// 返回當前字節的數量
return [movieSection count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @" MovieCell ";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (isSearchOn) {
NSString *title = [searchResult objectAtIndex:indexPath.row];
cell.textLabel.text = title;
} else {
// 獲取節點的年份
NSString *year = [years objectAtIndex:[indexPath section]];
// 獲取年份內所有電影數組
NSArray *movie = [movieTitles objectForKey:year];
// 根據數組獲取電影的標題
cell.textLabel.text = [movie objectAtIndex:[indexPath row]];
cell.detailTextLabel.text = @" 主演:周星馳 ";
}
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (isSearchOn)
{
return nil;
}
else
{
// 獲取年份
NSString *year = [years objectAtIndex:section];
return year;
}
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- ( void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#pragma mark - 添加搜索方法與事件
// 事件:搜索框開始輸入字符
-( void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
// 進入搜索狀態
isSearchOn = YES;
// 不能選擇行
canSelectRow = NO;
// 關閉滾動條的顯示
self.tableView.scrollEnabled = NO;
}
// 事件:搜索框中文字發生變化觸發
-( void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([searchText length]> 0)
{
isSearchOn = YES;
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self searchMoviesTableView];
}
else
{
isSearchOn = NO;
canSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
// 方法:搜索結果
-( void) searchMoviesTableView
{
[searchResult removeAllObjects];
for (NSString *str in listOfMovies) {
NSRange titleResultsRange=[str rangeOfString:searchBar.text
options:NSCaseInsensitiveSearch];
if(titleResultsRange.length> 0)
[searchResult addObject:str];
}
}
// 事件:鍵盤上的搜索按鈕事件
-( void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self searchMoviesTableView];
}
// 事件:搜索框里取消按鈕事件
-( void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
isSearchOn = NO;
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
self.navigationItem.rightBarButtonItem = nil;
[self.searchBar resignFirstResponder];
[self.tableView reloadData];
}
@end
12. View與Controller 綁定一下關系(如何綁定?如有不懂的童鞋,請找谷老師)
13. 最終效果圖如下:
14. 附上代碼地址:源代碼
搞定,收工,開周例會