TableView\cell常见属性\TableView常见属性\cell的循环利用\数据刷新

3.cell常见属性

tableView展示数据的步骤:
1.tableView有一个数据源属性, 如果想充当tableView的数据源, 必须要遵守对应的协议, 任何对象都可以充当TableView的数据源, 只要其遵守协议, 实现相应的方法

协议里面有一些方法, 方法里面最基础的有一开始的三个方法

属性:

  1. accessoryType: 属性作用:
    设置右边指示器的类型(每一个cell显示的)例如在设置中每一个cell右边有一个箭头, 这个箭头就是指示器
  • UITableViewCellAcessoryDislosureIndicator指示器为箭头
  • UITableViewCellAcessoryCheckmark指示器为对勾
  • [站外图片上传中……(1)]指示器为圆圈箭头
  • UITableViewCellAccessoryDetailButton指示器为圆圈i

由于本人的语言不是很生动, 所以上面对指示器描述不是很准确,希望大家自己试试

  1. accessoryView: (如果系统给的指示器不够用, 我们可以利用这个增加自己需要的控件)
    例如: cell.accessoryView = [[UISwich alloc] init];这个就是一个开关
  2. backgroundView:设置背景
     // 设置背景(背景view不用设置尺寸, backgroundView的优先级 > backgroundColor)
    UIImageView *bgView = [[UIImageView alloc] init];
    bgView.image = [UIImage imageNamed:@"buttondelete"];
    cell.backgroundView = bgView;
  1. selectedBackgroundView选中时设置背景
 UIView *selectedbgView = [[UIView alloc] init];
 selectedbgView.backgroundColor = [UIColor greenColor];
cell.selectedBackgroundView = selectedbgView;

以上的两段代码就是如果设置,我们的背景图片, 当然,设置背景颜色, 也是类似的. 但是还是有些不同.

04-tableView的常见属性

1. separatorStyle:分隔线样式

每一行都有线, 这个就是分隔线

2. separatorColor:分隔线颜色

有时候, 我们的颜色种类可能不够
这个时候, 我们就要了解叫做RGB的东西

颜色有: 32位颜色, 24位颜色

R就是Red ; G就是Green ; B就是Blue

** 32位颜色分为**

  • Alpha : 8位(这个是透明)
  • Red : 8位
  • Green : 8位
  • Blue : 8位

** 24位颜色分为**

  • Red : 8位
  • Green : 8位
  • Blue : 8位

然后, 我们在写程序中需要掌握的是:

我们的颜色是按照十六进制来存储的, 而且, 他们的存储方法是是这样的:

#ff ff ff ff // 这个代表的是白色(所有的颜色, 都是满格)透明度
前两个ff代表的是t, 后面的依次是R, G, B
-----------------------------------
#ff 00 00 00 // 这个代表的是黑色, 每一种颜色都是空

注意

  • 这里面的黑色是最纯洁的
  • 白色, 是最不纯洁的
  • 每一个颜色通道占据8个二进制位
  • 每一个颜色通道的取值范围是[0, 225]
#ff ff 00 00 // 这个代表的是红色

之所以讲这些, 是由于我们的这个有这么一个方法就是可以根据你自己的想法设计颜色

self.tableView.separatorColor = [UIColor colorWithRed: CGFloat green: CGFloat blue: CGFloat alpha: CGFloat];

要注意我在上面每一个参数的写法:

self.tableView.separatorColor = [UIColor colorWithRed: 78/225.0 green: 100/225.0 blue: 225/225.0 alpha: 225/225.0];

这个是苹果官方要求我们这样写, 这样表示的是每一份颜色所占总的比例

3. TableHeadView:

在我们的手机新浪微博中, 这个头部的控件是用来放置我们的广告的, 所以以后, 我们再使用的时候, 就不需要增加scollView了

** 调用方法:**

self.tableView.headView = ......    

4. TablefootView:

用来加载更多时候用的, 我们在使用新浪微博, 或者在各大新闻软件中, 底部会有一个点击加载的地方

05. cell的循环利用

1. 分析

**1. ** 其实, 在我们的英雄展示那个程序的时候, 我们其中的一个方法- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath我们都知道, 我们一共有97个英雄, 但是这就意味着我们的这个方法会一次性调用97次吗???
答案是否定的, 其实, 我们的cell的创建不是一次完成的, 我们可以在这个方法中试着打印 , 我们会发现, 他会打印7次, 或者8次.
这是由于,苹果官方在开发的时候, 为了性能的优化, 有这样的一个规律:
每当有cell进入我们的视野的时候, 新进来的cell就会被创建. 但是, 如果cell离开我们的视野之后, 再进入视野, 这个cell又会被重新创建
这样就会导致我们的性能的损耗

**2. ** 所以在这里我们就用到了, 新的知识:

  • cell的循环利用
    注意: 假设,我们的手机屏幕只可以放下7个cell那么当我们将手机屏幕向下拖动的时候, 最多可以显示8个cell,当我们继续拖动的时候, 我们会发现, 手机屏幕中的第一个cell会离开我们的手机屏幕, 这个时候注意: 系统中TableView中会有一个缓存池, 而且这个缓存池系统会帮我们维护, 专门存放我们的这个离开手机屏幕的cell, 等到, 我们拖动到要显示第9个cell的时候, 我们可以判断缓存池中是否有cell , 如果有, 我们就直接拿过来, 并将以前的数据覆盖掉.
  • 离开屏幕就到缓存池, 出现新的cell就先到缓存池找是否有cell如果有就直接覆盖数据, 拿过来用. 如果没有, 就创建一个新的cell
  • 当然, 以后我们的需要使用TableView中更加复杂的东西的时候, 我们的缓存池可能存放的不止一种cell这个时候, 我们就需要在提前对我们的每一个cell加一个标识, 方便以后查找

2. 步骤:

所以根据上的说的, 我们想要实现cell循环使用需要以下三步:

  1. 通过一个标识去缓存池中寻找可循环利用的cell
  2. 如果缓存池中找不到可循环的cell ; 创建一个新的cell并给其贴一个标识
  3. cell设置新的数据

3. 代码重写:

// 离开屏幕的cell会怎样

/**
 *  每当有一个cell进入视野范围内,就会调用
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   // static修饰局部变量:可以保证局部变量只分配一次存储空间(只初始化一次)
  static NSString *ID = @"hero";

    // 1.通过一个标识去缓存池中寻找可循环利用的cell
    // dequeue : 出列 (查找)
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 2.如果没有可循环利用的cell
     if (cell == nil){
       cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }

     // 3.给cell设置新的数据
     // 取出模型
    MJHero *hero = self.heros[indexPath.row];

    // 设置cell的数据
     cell.textLabel.text = hero.name;
    cell.detailTextLabel.text = hero.intro;
     cell.imageView.image = [UIImage imageNamed:hero.icon];

    return cell;
}

6. 多组汽车品牌展示:

效果展示:

Snip20160314_6.png

1. 注意点

  • 今天的多组数据, 与以往不同.

先说plist文件的加载:
以往我们的plist文件的加载, 是只需要一个模型类. 今天做的这个程序是需要两个模型类, 一个用来存储: 汽车的数据
另一个使用来存储汽车组的数据

在我们的这个知识点中, 其实只有一个: 那就是关于字典转模型的更深一层的了解.

2. 知识点:

  1. 两个模型类:
    上面我们介绍到了, 一个模型类用来存储汽车组数据的, 因为我们的这次的plist文件要比以往复杂:
Snip20160314_7.png

而且, 我们以前在数组转模型的时候, 一行代码便可, 现在不可以了

**以前的代码: **

@implementation MJCar
+ (instancetype)carWithDict:(NSDictionary *)dict
{
     return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
     if (self = [super init]) {
         [self setValuesForKeysWithDictionary:dict];
     }
    return self;
}
@end

**现在的代码: **

@implementation MJCarGroup
+ (instancetype)groupWithDict:(NSDictionary *)dict
{
     return [[self alloc] initWithDict:dict];
}

- (instancetype)initWithDict:(NSDictionary *)dict
{
     if (self = [super init]) {
      // 赋值标题
        self.title = dict[@"title"];
    
        // 取出原来的字典数组
         NSArray *dictArray = dict[@"cars"];
    
         NSMutableArray *carArray = [NSMutableArray array];
         for (NSDictionary *dict in dictArray) {
             MJCar *car = [MJCar carWithDict:dict];
             [carArray addObject:car];
         }
         self.cars = carArray;
     }
     return self;
}
@end

这是由于, 一开始的第一个模型转数组的时候 , 它只是将他的title转成了模型, 而我们的car虽然是个模型, 因为他里面还有数组并没有转成模型, 所以,我们需要创建两个模型类


  1. 关于右边的那个索引条

右边的那个索引条是我们的数据源自带的一个方法, 上面的字母是我们提前在plist文件中有的.

那个索引条上面的字母是我们随意写的, 而且, 他是按照从上到下的顺序, 帮助我们进行快速查找, 假如说, 我们将AB的位置互相调换一下之后, 当我们点击B的时候, 他会向我们展示的是A类的汽车

3. 代码:

控制器.m文件

#import "MJViewController.h"
#import "MJCarGroup.h"
#import "MJCar.h"

@interface MJViewController ()<UITableViewDataSource>
/**
 *  车品牌组数据
*/
@property (nonatomic, strong) NSArray *groups;
@end

@implementation MJViewController

- (void)viewDidLoad
{
     [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (NSArray *)groups
{
     if (_groups == nil) {
         // 初始化
        // 1.获得plist的全路径
        NSString *path = [[NSBundle mainBundle] pathForResource:@"cars_total.plist" ofType:nil];
    
        // 2.加载数组
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
    
        // 3.将dictArray里面的所有字典转成模型对象,放到新的数组中
        NSMutableArray *groupArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
            // 3.1.创建模型对象
            MJCarGroup *group = [MJCarGroup groupWithDict:dict];
        
            // 3.2.添加模型对象到数组中
            [groupArray addObject:group];
     }
    
     // 4.赋值
      _groups = groupArray;
    }
    return _groups;
}

#pragma mark - 数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
     return self.groups.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     MJCarGroup *group = self.groups[section];

     return group.cars.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     // 1.定义一个循环标识
    static NSString *ID = @"car";

    // 2.从缓存池中取出可循环利用cell
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 3.缓存池中没有可循环利用的cell
     if (cell == nil) {
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }

    // 4.设置数据
    MJCarGroup *group = self.groups[indexPath.section];
    MJCar *car = group.cars[indexPath.row];

    cell.imageView.image = [UIImage imageNamed:car.icon];
    cell.textLabel.text = car.name;

    return cell;
}

/**
 *  第section组显示的头部标题
*/
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    MJCarGroup *group = self.groups[section];
    return group.title;
}

/**
*  返回右边索引条显示的字符串数据
*/
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    return [self.groups valueForKeyPath:@"title"];
}

// 这个是隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
 return YES;
}
@end

CarGroup. h

#import <Foundation/Foundation.h>

@interface MJCarGroup : NSObject
/**
*  这组的标题
*/
@property (nonatomic, copy) NSString *title;
/**
*  存放的所有的汽车品牌(里面装的都是MJCar模型)
*/
@property (nonatomic, strong) NSArray *cars;

+ (instancetype)groupWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end

CarGroup. m

#import "MJCarGroup.h"
#import "MJCar.h"

@implementation MJCarGroup
+ (instancetype)groupWithDict:(NSDictionary *)dict
{
     return [[self alloc] initWithDict:dict];
}

- (instancetype)initWithDict:(NSDictionary *)dict
{
     if (self = [super init]) {
        // 赋值标题
        self.title = dict[@"title"];
    
        // 取出原来的字典数组
        NSArray *dictArray = dict[@"cars"];
    
         NSMutableArray *carArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
              MJCar *car = [MJCar carWithDict:dict];
             [carArray addObject:car];
        }
        self.cars = carArray;
     }
    return self;
}
@end

Car.h

#import <Foundation/Foundation.h>

@interface MJCar : NSObject
/**
 *  图标
*/
@property (nonatomic, copy) NSString *icon;
/**
*  名称
 */
@property (nonatomic, copy) NSString *name;

+ (instancetype)carWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end

Car.m

#import "MJCar.h"

@implementation MJCar
+ (instancetype)carWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];
}

- (instancetype)initWithDict:(NSDictionary *)dict
{
     if (self = [super init]) {
         [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}
@end

7. 数据刷新

**目的: **
上午我们讲了一些关于汽车品牌的, 但是, 我们注意到那上面的数据都是死的, 不能修改, 所以今天我们就做这个刷新的功能

我们今天利用上次的英雄展示那个应用 来完成今天的知识点. 效果就是:
当我们点击其中的一行的时候, 会弹出一个框, 然后里面课可以修改我们英雄的数据

1. 效果图:

Snip20160314_8.png

2. 步骤:

  • 在我们的storyboard界面将我们的tableView连线. 和我们的控制器链接 ,然后, 再遵守我们的协议, 使之成为我们tatableView的代理

  • 由于我们在后面同样需要弹框(AlerView)这个效果, 而且要监听AlerView内部 确认或者取消按钮的点击, 所以同样的我们需要遵守AlerView的协议成为他的代理

  • 协议名称:

      <UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate>
    
1. tableView的代理
  • 取得我们被点击的模型
  • 设置弹框
  • 设置对话框的类型
  • 取得唯一的那个文本框,显示英雄的名称
  • 绑定行号到alertView上

绑定行号的作用是后面我们在修改数据模型的时候, 可以取得该行号, 当然, 这个其实是我们的AlerView的独有的渠道, 为了就是方便我们的方法之间传递参数

**代码: **

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
     // 1.取得被点击这行对应的模型
    MJHero *hero = self.heros[indexPath.row];

    // 弹框
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"数据展示" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];

    // 设置对话框的类型
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;

    // 取得唯一的那个文本框,显示英雄的名称
    [alert textFieldAtIndex:0].text = hero.name;

    [alert show];

    // 绑定行号到alertView上
     alert.tag = indexPath.row;
}

2.

/**
*  点击了alertView上面的按钮就会调用这个方法
 *
 *  @param buttonIndex 按钮的索引,从0开始
*/
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0) return;

    // 按钮的索引肯定不是0

    // 1.取得文本框最后的文字
    NSString *name = [alertView textFieldAtIndex:0].text;
    // 2.修改模型数据
    int row = alertView.tag;
    MJHero *hero = self.heros[row];
    hero.name = name;

    // 3.告诉tableView重新加载模型数据
    // reloadData : tableView会向数据源重新请求数据
    // 重新调用数据源的相应方法取得数据
    // 重新调用数据源的tableView:numberOfRowsInSection:获得行数
    // 重新调用数据源的tableView:cellForRowAtIndexPath:得知每一行显示怎样的cell
    // 全部刷新
//    [self.tableView reloadData];

    // 局部刷新
    NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:0];
     [self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationBottom];
}

作者说:

这个是我现在学的所有的东西了, 现在我用的是Markdown不用像以前一样, 还要把笔记整理一遍

这样做的好处就是更新的更加容易, 也快一点.

坏处就是可能我在做笔记的时候, 知识点比较散乱, 所以各位见谅哈!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容