团购案例:加载数据并自定义Cell

第一步:建立商品模型

在这里插入图片描述
GZGoods.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface CZGoods : NSObject
@property (nonatomic,copy)NSString *buyCount;
@property (nonatomic,copy)NSString *price;
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *icon;

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

NS_ASSUME_NONNULL_END

CZGoods.m

#import "CZGoods.h"

@implementation CZGoods
- (instancetype)initWithDict:(NSDictionary *)dict
{
    if(self = [super init]){
        //把字典中的键对应的每一个值取出来放到了self中
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+ (instancetype)goodsWithDict:(NSDictionary *)dict
{
    return [[self alloc]initWithDict:dict];
}
@end

第二步:懒加载数据

在控制器ViewController.m中
ViewController.m

#import "ViewController.h"
#import "CZGoods.h"
@interface ViewController ()

//用来存储所有的团购商品的数据
@property (nonatomic,strong) NSArray *goods;

@end

@implementation ViewController



//懒加载数据
#pragma mark -懒加载数据
- (NSArray *)goods
{
    if(_goods == nil){
        NSString *path = [[NSBundle mainBundle]
                          pathForResource:@"tgs.plist" ofType:nil];
        //加载成一个字典的数组
        NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
        
        //把字典转模型
        NSMutableArray *arrayModels = [NSMutableArray array];
        
        //遍历
        for(NSDictionary *dict in arrayDict){
            CZGoods *model = [CZGoods goodsWithDict:dict];
            [arrayModels addObject:model];
        }
        _goods = arrayModels;
    }
    return _goods;
}


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


@end

第三步:拉一个UITableView

设置数据源,拖到View Controller
所以这个类需要遵守< UITableViewDataSource>这个协议
在这里插入图片描述

#import "ViewController.h"
#import "CZGoods.h"
@interface ViewController ()<UITableViewDataSource>
第四步:在这个类里面实现数据源方法

把模型数据设置给单元格时候,需要cell.XXX和model.XXX都要知道,是个小缺点哦。控制器知道的太多了,获取太多单元格内部信息。当前的cell封装的不够完整

//数据源方法
#pragma mark -数据源方法

//因为只有一组,所以下面这个方法可以不写
//-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//{
//    return 1;
//}

//goods有多少个对象就是多少个数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.goods.count;
}

//每一行显示单元格,返回值类型是UITableViewCell类型
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1、获取模型数据,拿到第几行数据,就是第几个模型
    CZGoods *model = self.goods[indexPath.row];
    
    //2、创建单元格
    //先创建一个ID,再根据ID去取,有的话直接取,没有的话要创建。因为是要重用的。
    static NSString *ID = @"goods_cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if(cell == nil){
        //创建单元格
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    

    
    //3、把模型数据设置给单元格
    cell.imageView.image = [UIImage imageNamed:model.icon];
    cell.textLabel.text = model.title;
        //价格之前有符号,因此要拼接字符串
        //数字:cell.detailTextLabel.text = model.price;
        //拼接¥:cell.detailTextLabel.text = [NSString stringWithFormat:@"¥ %@",model.price];
        //一个单元格默认只有这三个控件了。,要实现第四个控件只能进行拼接啦
    cell.detailTextLabel.text = [NSString stringWithFormat:@"¥ %@               %@人已购买",model.price,model.buyCount];
    
    //4、返回单元格
    return cell;
    
}

第五步:隐藏状态栏
//隐藏状态栏
#pragma mark -隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
    return YES;
}
第六步:调整细节,创建xib

想实现价格和几人已购买颜色设置不同,位置对齐。
如果仅仅还是使用同一个标签的话,就比较难实现了,因此从单元格下手吧!自带的单元格就不够用了,可以自定义单元格,重新进行创建单元格,使用xib来描述一个单元格。

1、在Views里面建立一个空的xib
在这里插入图片描述
2、在这个xib中,只需要拖单元格就可以啦,拖好单元格、标签,就可以设置大小颜色等
在这里插入图片描述

3、样式摆好了,接下来一定会使用代码来设置xib的这几个字控件的数据,所以需要通过拖线用一些属性来引用这些数据,来通过属性访问控件。
拖线的话,默认是UITableViewCell类的对象,但是是不能向这个系统的类里面添加属性,拖线的,因此使用xib,要配合建一个类,描述这个单元格的类。需要自定义一个类,继承UITableViewCell,把自己的类名写在这里。在这里插入图片描述
4、建一个类:CZGoodsCell
Subclass of:UITableViewCell

在这里插入图片描述

5、因为这个cell里面没有类拓展,所以没法子拖。
所以写上interface

@interface CZGoodsCell()

6、拖线
在这里插入图片描述
依次拖好,如下:

在这里插入图片描述

第七步:以xib的形式创建单元格

加载xib,mainBundle是安装在手机根目录,在这里找到xib.这里loadNibNamed返回的数组类型,因为多个字控件,因为目前只有一个子控件,所以使用firstObject拿到第一个就ok啦

 CZGoodsCell *cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGoodsCell" owner:nil options:nil]firstObject];

这里也要实现重用哦

   //2、通过xib的方式创建单元格

 
    static NSString *ID = @"goods_cell";
    CZGoodsCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if(cell == nil)
    {
    cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGoodsCell" owner:nil options:nil] firstObject];
    }

但是新建的时候,没有设置可重用ID,要在这里设置一下!!
在这里插入图片描述

这里面其实也可以稍微改进一下下哦
在自定义的cell中封装一个类方法,通过这个类方法创建一个单元格
所以也封装到xib中就可以啦

(1)在CZGoodsCell.h中

//封装一个创建自定义cell的方法
+ (instancetype)goodsCell;

(2)在CZGoodsCell.m中

+ (instancetype)goodsCell
{
    static NSString *ID = @"goods_cell";
     CZGoodsCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
     if(cell == nil)
     {
     cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGoodsCell" owner:nil options:nil] firstObject];
     }
}

但是这里面的tableView是不存在的

所以要在封装一个创建自定义cell的方法这里加上去

+ (instancetype)goodsCellWithTableView:(UITableView *)tableView;
+ (instancetype)goodsCellWithTableView:(UITableView *)tableView
{
    static NSString *ID = @"goods_cell";
     CZGoodsCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
     if(cell == nil)
     {
     cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGoodsCell" owner:nil options:nil] firstObject];
     }
    return cell;
}

这个时候,创建单元格可以直接通过

    //2、通过xib的方式创建单元格
    CZGoodsCell *cell = [CZGoodsCell goodsCellWithTableView:tableView];;
第八步:把模型数据设置给单元格

在控制器中直接给cell的每个子控件赋值数据造成的问题
1、控制器强依赖于Cell,一旦cell内部的子控件发生了变化,那么控制器中的代码也得改,这就造成了紧耦合
2、cell的封装不够完整,凡是用到这个cell的地方,每次都要编写为cell的子控件依次赋值的语句,比如cell.xxx = model.title
3、解决:直接把模型传递给自定义Cell,然后在自定义cell内部解析model中的数据赋值给自定义的cell内部的子控件
在这里插入图片描述

//3、把模型数据设置给单元格
    cell.goods = model;

把模型直接赋值给goods属性,goods拿到之后需要重新解析

自定义单元格中加入这个属性
需要重新goods的set方法

//  CZGoodsCell.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@class CZGoods;
@interface CZGoodsCell : UITableViewCell
@property(nonatomic,strong) CZGoods *goods;
@end

NS_ASSUME_NONNULL_END


在CZGoodsCell.m中写出set方法

- (void)setGoods:(CZGoods *)goods
{
    _goods = goods;
    //把模型的数据设置给子控件
    self.imgViewicon.image = [UIImage imageNamed:goods.icon];
    self.lblTitle.text = goods.title;
    self.lblPrice.text = [NSString stringWithFormat:@"¥ %@",goods.price];
    self.lblBuyCount.text = [NSString stringWithFormat:@"%@人已购买 ",goods.buyCount];
    
}
第九步:小结

所以,这样写下来,自定义cell四句话就搞定啦


//每一行显示单元格,返回值类型是UITableViewCell类型
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1、获取模型数据,拿到第几行数据,就是第几个模型
    CZGoods *model = self.goods[indexPath.row];
    
    //2、通过xib的方式创建单元格
    CZGoodsCell *cell = [CZGoodsCell goodsCellWithTableView:tableView];
    
    //3、把模型数据设置给单元格
    cell.goods = model;
    //4、返回单元格
    return cell;
    
}

通过xib方式实现自定义cell
1、创建一个xib文件
2、在xib中拖一个UITableViewCell设置号高度宽度
3、向UITableViewCell中拖子控件
4、新建一个自定义的UITableViewCell类与xib中的这个cell相关联
新建一个类继承自UITableViewCell
通过拖线的方式将cell中的子控件拖到这个类的属性上,方便后续使用
5、改造数据源方法:cellForRowAtIndex中的创建cell的代码,通过加载xib的方式来创建cell

UITableViewCell *cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGoodsCell" owner:nil options:nil] firstObject];

为了可以重用xib中的Cell,所以要设置xib中的cell
的identifier,这个identifier就是将来的可重用ID
6、设置cell中的子控件的数据
在外部访问不到cell中的子控件的内容,解决方法:把模型数据传递给cell对象,由cell对象内部自己来解析模型数据,并把数据设置到对应的子控件中

在自定义cell的类中创建一个模型类型的属性,重写该属性的set方法,在set方法中将数据赋值给控件

7、完成数据列表的显示,运行可看到效果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Αиcíеиτеǎг

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值