UI基础(四)之tableView (cell重用、原型cell、静态cell)/xib注意事项

---恢复内容开始---

1.Cell的重用机制:

如下图所示:我们在写tableview的数据源方法的时候,在第三个方法中通常会碰到定义重用cell的三步骤

 

#pragma mark -- 数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //1.定义重用标识符
    static NSString *identifier = @"cellID";
    //2.根据重用标识符去缓存区中查找重用cell
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    //3.判断是否有重用cell
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    return cell;
}

 

cell重用机制:如上图:最开始的时候,tableview是没有任何cell,此时缓存区也没有重用的cell,数据源方法会走(

 //2.根据重用标识符去缓存区中查找重用cell

)这个方法,显然是找不到的,那么继续走第三个方法,创建一个cell,仔细看这个方法,是带有重用标识符的,这个方法做了什么呢?

如下图:这个方法给创建好的cell一个重用标识符,然后再走(

cellForRowAtIndexPath

)方法,继续创建,直到创建完成,当我们上下拖动时,就会调用缓存区中的重用cell,从而实现cell的重用.

 

 2.cell也可以用加载xib

//
//  ViewController.m
//  04-原型cell
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<UITableViewDataSource>

@end

@implementation ViewController


#pragma mark --UITableViewDataSource


//返回组

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{

    return 1;

}


//返回行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return 10;


}

//返回cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{


    //1. 定义重用标识
    static NSString *reuseId = @"cell";
    
    //2. 获取重用cell
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
    
    
    //3. 判断cell是否存在
    if (!cell) {
        //4. 创建cell
        NSLog(@"创建新的cell %ld",indexPath.row);
        cell = [[[NSBundle mainBundle]loadNibNamed:@"MyCell" owner:nil options:nil]lastObject];
    }
    
    //5. 设置属性
//    cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld行",indexPath.section,indexPath.row];
    
    
    //6. 返回cell
    return cell;
    

}

@end

通过xib加载cell,其实也就是自定义的cell,之所以引入这种加载方式,其实就是因为系统的cell满足不了我们要的需求.

 3.原型cell的小结:

首先:什么是原型cell?为什么引入?

 原型cell,其实呢,就是在storyboard中,拉入一个UItableviewController,每一个UItableviewController都自带cell,这个cell就是原型cell

//
//  ViewController.m
//  04-原型cell
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<UITableViewDataSource>

@end

@implementation ViewController


#pragma mark --UITableViewDataSource


//返回组

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{

    return 1;

}


//返回行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return 10;


}

//返回cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{


    //1. 定义重用标识
    static NSString *reuseId = @"cell";
    
    //2. 获取重用cell
    // 原型cell--> 只要直接在对应storyboard中,对应的UITableViewCell上设置一个重用的标识,就可以直接加载
    //  原型cell的加载,不会走第四步创建
    //  虽然第四步创建,说的是如果没有重用的cell,就创建新的cell  -->虽然原型cell不会走第四步新创建的过程
    //  但是绝对不代表说cell 就不会创建了-->只不过它的创建由系统完成
    //
    // 当使用原型cell的时候,系统会先从UITableView中获取是否有重用的cell,如果没有系统自己去完成创建,如果有就直接使用
    // 而创建的方式,就是根据判断对应storyboard中,是否有一个cell的标识属性,跟获取重用的标识属性一致
//    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
    
    
//    unable to dequeue a cell with identifier cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
    //forIndexPath 多了这样一个参数-->参数的用处,首先indexPath无论有任何值,都没有任何意义,它在这里的唯一作用,就是用来判断,是否是从原型cell中进行创建
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath];
    
    
    //3. 判断cell是否存在
//    if (!cell) {
//        //4. 创建cell
//        NSLog(@"创建新的cell %ld",indexPath.row);
//        cell = [[[NSBundle mainBundle]loadNibNamed:@"MyCell" owner:nil options:nil]lastObject];
//    }
    
    //5. 设置属性
//    cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld行",indexPath.section,indexPath.row];
    
    
    //6. 返回cell
    return cell;
    

}






@end

 

原型cell:直接从SB 中加载的,这里面有一些注意点:

区别两个方法:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath];

 这两个方法都是通过重用标识符去查找是否有重用的cell,都能起到cell重用的作用,但第二个方法中多了个forIndexPath参数,

作用是只会加载原型cell,如果标识符不匹配,直接报错(crash掉),但是第一个方法不会,他会找标识符,如果原型cell标识符不匹配,

如上例所示,他会找xib中的标识符,如果xib中的标识符匹配,就会加载xib,如果SB(原型cell)和xib中标识符都匹配,那么优先加载SB,

其实:只要原型cell可以加载,那么tableview就不会加载其他的(如xib)cell了.

 

那么,引入原型cell的好处是什么呢?

 

//返回cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{


    //1. 定义重用标识
    NSString *reuseId = @"cell";
    
    //2. 获取重用cell的时候,使用一个带indexPath参数的方法
    // 通过这个标识,如果加载的不是storyboard中的原型cell就会报错
    
    // 使用原型cell的好处:
    //  1. 代码少写了
    //  2. 系统在加载cell,cell的高度,系统会自动判断进行自动的设定,可以不需要通过代码的方式进行设置
    会根据自己拉多大自动设置行高
    //  3. 扩充:当界面中cell的样式不一样的时候,可以简单通过一个标识进行区分,不需要写太多的代码
    UITableViewCell *cell;
    if (indexPath.row < 3) {
        
        cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath];
    }else{
    
        cell = [tableView dequeueReusableCellWithIdentifier:@"cell1" forIndexPath:indexPath];
    }
    
    
    //3. 设置属性
//    cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld 行",indexPath.section,indexPath.row];
    
    
    //4. 返回cell
    return cell;

4.静态cell:

静态cell只能在UItableviewController中使用,好处是不需要写数据源方法,也不需要写代理方法,但原型cell不写数据源方法和代理是不能加载出界面的.

记住:这个image是静态cell自带的,所以可以直接设置,会自动选好位置,不用自己再拖一个新的imageView进去,所以很牛逼!

 

 

 

 注意点:xib使用注意事项

/**
 *  这个方法可以当成是 viewDidLoad方法去看到
 *  界面加载就会调用-->唯一的区别在awakeFromNib 从nib中唤醒
 * 这个方法,只有从xib中加载控件的时候才会调用
 * 只在初始化的时候调用
 * 如果不是在xib中创建,那么就不会调用
 * 以后用的也不是很多<但是做个记忆,一旦有需求,从xib中加载必须做什么事情的时候
 */
- (void)awakeFromNib {
//    NSLog(@"从xib中加载控件");
}

/**
 *  设置点击的状态
 *
 *  @param selected 是否允许保持点击的状态
 */
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    NSLog(@"被点击了");
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

 

posted @ 2016-11-04 02:12  忆缘晨风  阅读(618)  评论(0编辑  收藏  举报