Loading

UITableView 分组显示数据与搜索,数据源plist [xcode 4.4.1]

本篇学习目标:

1. 学习使用读取plist

2. UITableView 分组显示数据

3. UITableView 加上搜索功能

 

不‘费’话,直接跟我一起来,进行如下操作:

 

1. 创建项目,在此略过,可以参考前篇文章,在此只显示一个项目的图:

 

2. 添加plist 文件

 PS: plist文件是什么呢? 它全名是:Property List,属性列表文件,它是一种用来存储串行化后的对象的文件。属性列表文件的扩展名为.plist,因此通常被称为plist文件。文件是xml格式 的。Plist文件通常用于储存用户设置,也可以用于存储捆绑的信息。

 

data.plist 文件图片如下:

 

查看源代码,如下

View Code
<?xml version="1.0" encoding="UTF-8"?>
<!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 years;
@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. 绑定数据源


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // 返回节点数,就是显示几个组,我们这里是按年份显示数据
    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 文件

View Code
//
//  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 文件 注解在代码中,请大家仔细看清楚

View Code
//
//  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. 附上代码地址:源代码

 

搞定,收工,开周例会

posted @ 2012-08-31 08:43  草梵  阅读(2557)  评论(5编辑  收藏  举报