简单的TableView

背景知识

每个表都是UITableView的实例,表中的每一行都是UITableViewCell的实例。

TableView的种类

  • Grouped table
  • Plain table without index
  • Plain table with index

NSIndexPath

  • NSIndexPath.section 返回int,表示第几个Section
  • NSIndexPath.row 返回int,表示该Section下的第几行

UITableViewCell包含的元素

  • Image    (imageView.image)
  • Text Label (textLabel.text, textLabel.font)
  • Detail Text Label (detailTextLabel.text)

UITableViewCell样式

  • UITableViewCellStyleDefault   //左文,图(如果有则最左)
  • UITableViewCellStyleSubtitile   //左文,图(如果有则最左),detailText在Text下面
  • UITableViewCellStyleValue1        //左文,图(如果有则最左),detailText在最右
  • UITableViewCellStyleValue2        //左文,图(如果有则最左),detailText在Text右边

 

简单例子

StoryBoard拖入一个TableView,然后设置DataSource和Delegate为ViewController。
ViewController.h声明协议

#import <UIKit/UIKit.h>

@interface XYZViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
@end

ViewController.m文件如下

//
//  XYZViewController.m
//  TableView
//
//  Created by Norcy on 14-7-24.
//  Copyright (c) 2014年 QQLive. All rights reserved.
//

#import "XYZViewController.h"

@interface XYZViewController ()
@property (strong, nonatomic)NSArray *array;
@end

@implementation XYZViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.array = [[NSArray alloc] initWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", @"13", @"14", @"15", nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark -
#pragma mark Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.array count];
}

#pragma mark Delegate Methods
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellId = @"MyCell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellId];
    }
    
    cell.textLabel.text = self.array[indexPath.row];
    
    UIImage *image = [UIImage imageNamed:@"1.png"];
    
    cell.imageView.image = image;
    
    cell.detailTextLabel.text = @"Details";
    
    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.row;
}
@end
View Code

代码说明

代码说明1:

static NSString *CellID = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID];
}

从ReusableCell的队列中取出带有Identifier标识的Cell,如果Cell为空,则新创建一个。
ReusableCell队列是专门存放那些生成过的,但是后来由于滚动tableView而隐藏起来的cell。这样做可以节约资源。
注意CellIdentifier这个参数是可以自定义的,如果使用storyboard的话需要跟storyboard中的cell的Identifier相同。

  • dequeueReusableCellWithIdentifier: 可能返回nil(没有为TableView注册Cell的情况返回nil)
  • dequeueReusableCellWithIdentifier:forIndexPath: 不可能返回nil

所以如果使用dequeueReusableCellWithIdentifier:forIndexPath的话就不用检查nil的情况了。

But,以上这种写法已经过时了。推荐最新写法

[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CELL_ID];
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CELL_ID forIndexPath:indexPath];

如果TableView已经注册了Cell,那么dequeueReusableCellWithIdentifier:一定不为空;因为当系统从重用队列中取cell取不到的时候,会自动帮我们生成并初始化一个cell。

所以建议直接用registerClass:forCellReuseIdentifier:CELL_ID + dequeueReusableCellWithIdentifier:forIndexPath: 这个组合。

代码说明2:

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.row;
}

设置缩进。

代码说明3:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0)
        return nil;
    else
        return indexPath;
}

选中某行之前调用,返回nil表示该行不能被选择,返回indexPath表示可以继续选择(可以返回其他路径但最好不要更改用户的选择,所以一般返回nil或indexPath来表示禁止或允许某个选择)

代码说明4:

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

选中某行之后调用,一般要调用deselectRowAtIndexPath

代码说明5:

cell.textLabel.font = [UIFont boldSystemFontOfSize:50];

- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 70;
}

设置TableViewCell的行高以适应TableViewCell的字体

附录,联系人Demo(Based in IOS7.0) or 直接查看主要代码

//
//  ViewController.m
//  Contact
//
//  Created by Norcy on 15/4/16.
//  Copyright (c) 2015年 Norcy. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
{
}
@property (strong, nonatomic) NSDictionary* names;
@property (strong, nonatomic) NSArray* keys;
@end

NSMutableArray* filteredNames;
UISearchDisplayController* searchController;
static NSString* CELL_ID = @"MyCell";

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Screen
    int screenWidth = [[UIScreen mainScreen] bounds].size.width;
    int screenHeight = [[UIScreen mainScreen] bounds].size.height;

    //Filter
    filteredNames = [[NSMutableArray alloc] init];

    //TableView
    UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight)];

    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CELL_ID];

    tableView.delegate = self;

    tableView.dataSource = self;

    tableView.tag = 1;

    UIEdgeInsets insets = tableView.contentInset;    //设置与屏幕顶部的距离,防止被状态栏挡住

    insets.top = 20;

    [tableView setContentInset:insets];

    //Search Bar
    UISearchBar* searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight / 12)];

    tableView.tableHeaderView = searchBar;

    searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];

    searchController.delegate = self;

    searchController.searchResultsDataSource = self;

    //Names and Keys
    NSString* path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];

    self.names = [NSDictionary dictionaryWithContentsOfFile:path];

    self.keys = [[self.names allKeys] sortedArrayUsingSelector:@selector(compare:)];

    [self.view addSubview:tableView];
}

#pragma mark -
#pragma mark Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
    if (tableView.tag == 1)
        return [self.keys count];
    else
        return 1;
}

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView.tag == 1)
    {
        NSString* key = self.keys[section];
        NSArray* curSection = self.names[key];
        return [curSection count];
    }
    else
        return [filteredNames count];
}

- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
    if (tableView.tag == 1)
        return self.keys[section];
    else
        return nil;
}

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CELL_ID forIndexPath:indexPath];
    
//    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CELL_ID];
    
//    if (cell == nil)
//    {
//        NSLog(@"asd");
//        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CELL_ID];
//    }

    if (tableView.tag == 1)
    {
        NSString* key = self.keys[indexPath.section];

        NSArray* curSection = self.names[key];

        cell.textLabel.text = curSection[indexPath.row];
    }
    else
        cell.textLabel.text = filteredNames[indexPath.row];

    return cell;
}

#pragma mark Delegate Methods
//显示索引
- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView
{
    if (tableView.tag == 1)
        return self.keys;
    else
        return nil;
}

- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark Search Delegate Methods
- (void)searchDisplayController:(UISearchDisplayController*)controller didLoadSearchResultsTableView:(UITableView*)tableView
{
    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CELL_ID];
}

- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchString:(NSString*)searchString
{
    [filteredNames removeAllObjects];

    if (searchString.length > 0)
    {
        NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary* bindings) {
            NSRange range = [evaluatedObject rangeOfString:searchString options:NSCaseInsensitiveSearch];
            return range.location != NSNotFound;
        }];

        for (NSString* key in self.keys)
        {
            NSArray* matches = [self.names[key] filteredArrayUsingPredicate:predicate];

            [filteredNames addObjectsFromArray:matches];
        }
    }

    return YES;
}

@end
View Code

 

原文地址:https://www.cnblogs.com/chenyg32/p/3866280.html