1.自定义cell
有时候需要自定义UITableViewCell(用一个子类继承UITableViewCell),而且每一行用的不一定是同一种UITableViewCell,所以一个UITableView可能拥有不同类型的UITableViewCell,对象池中也会有很多不同类型的UITableViewCell,那么UITableView在重用UITableViewCell时可能会得到错误类型的UITableViewCell
解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象
// 1.定义一个cell的标识
static NSString *ID = @"mjcell";
// 2.从缓存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 3.如果缓存池中没有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
// 4.设置cell的属性...
return cell;
新建一个xib文件描述一个view的内部结构(假设叫做MJTgCell.xib)
新建一个自定义的类
(自定义类需要继承自系统自带的view, 继承自哪个类, 取决于xib根对象的Class)
新建类的类名最好跟xib的文件名保持一致(比如类名就叫做MJTgCell)
将xib中的控件 和 自定义类的.m文件 进行连线
提供一个类方法返回一个创建好的自定义view(屏蔽从xib加载的过程)
提供一个模型属性让外界传递模型数据
重写模型属性的setter方法,在这里将模型数据展示到对应的子控件上面
解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象
2.Cell的重用代码
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{// 1.定义一个cell的标识
static NSString *ID = @"mjcell";
// 2.从缓存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 3.如果缓存池中没有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
// 4.设置cell的属性...
return cell;
3.使用xib封装一个view的步骤
新建一个xib文件描述一个view的内部结构(假设叫做MJTgCell.xib)
新建一个自定义的类
(自定义类需要继承自系统自带的view, 继承自哪个类, 取决于xib根对象的Class)
新建类的类名最好跟xib的文件名保持一致(比如类名就叫做MJTgCell)
将xib中的控件 和 自定义类的.m文件 进行连线
提供一个类方法返回一个创建好的自定义view(屏蔽从xib加载的过程)
提供一个模型属性让外界传递模型数据
重写模型属性的setter方法,在这里将模型数据展示到对应的子控件上面
4.实例通过自定义cell实现下面效果图
5.实现步骤
5.1搭建界面9MJTgCell.xib)
5.2plist文件
5.3代码实现
5.3.1使用xib封装一个view
使用xib封装一个view的步骤
新建一个xib文件描述一个view的内部结构(假设叫做MJTgCell.xib)
新建一个自定义的类
(自定义类需要继承自系统自带的view, 继承自哪个类, 取决于xib根对象的Class)
新建类的类名最好跟xib的文件名保持一致(比如类名就叫做MJTgCell)
将xib中的控件 和 自定义类的.m文件 进行连线
提供一个类方法返回一个创建好的自定义view(屏蔽从xib加载的过程)
提供一个模型属性让外界传递模型数据
重写模型属性的setter方法,在这里将模型数据展示到对应的子控件上面
新建一个自定义的类
(自定义类需要继承自系统自带的view, 继承自哪个类, 取决于xib根对象的Class)
新建类的类名最好跟xib的文件名保持一致(比如类名就叫做MJTgCell)
将xib中的控件 和 自定义类的.m文件 进行连线
提供一个类方法返回一个创建好的自定义view(屏蔽从xib加载的过程)
提供一个模型属性让外界传递模型数据
重写模型属性的setter方法,在这里将模型数据展示到对应的子控件上面
MJTgCell类
//
// MJTgCell.h
#import <UIKit/UIKit.h>
@class MJTg;
@interface MJTgCell : UITableViewCell //xib里的小控件是装到这个控件里面的,所以要继承这个控件
/**
* 通过一个tableView来创建一个cell
*/
+ (instancetype)cellWithTableView:(UITableView *)tableView;
/**
* 团购模型
*/
@property (nonatomic, strong) MJTg *tg;
@end
//
// MJTgCell.m
#import "MJTgCell.h"
#import "MJTg.h"
@interface MJTgCell()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleView;
@property (weak, nonatomic) IBOutlet UILabel *priceView;
@property (weak, nonatomic) IBOutlet UILabel *buyCountView;
@end
@implementation MJTgCell
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"tg";
MJTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //循环利用cell
if (cell == nil) { //如果缓存池里面没有cell就自己创建cell
// 从xib中加载cell
cell = [[[NSBundle mainBundle] loadNibNamed:@"MJTgCell" owner:nil options:nil] lastObject];
}
return cell;
}
- (void)setTg:(MJTg *)tg //把模型对象传递进来设置数据
{
_tg = tg;
// 1.图片
self.iconView.image = [UIImage imageNamed:tg.icon];
// 2.标题
self.titleView.text = tg.title;
// 3.价格
self.priceView.text = [NSString stringWithFormat:@"¥%@", tg.price];
// 4.购买数
self.buyCountView.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
}
@end
5.3.2模型类
//
// MJTg.h
//一个模型对象就是一行
#import <Foundation/Foundation.h>
@interface MJTg : NSObject
/**
* 标题
*/
@property (nonatomic, copy) NSString *title;
/**
* 价格
*/
@property (nonatomic, copy) NSString *price;
/**
* 图片
*/
@property (nonatomic, copy) NSString *icon;
/**
* 购买人数
*/
@property (nonatomic, copy) NSString *buyCount;
+ (instancetype)tgWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end
//
// MJTg.m
#import "MJTg.h"
@implementation MJTg
+ (instancetype)tgWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
@end
5.3.3控制器
//
// MJViewController.m
#import "MJViewController.h"
#import "MJTg.h"
#import "MJTgCell.h"
@interface MJViewController () <UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSArray *tgs;
@end
@implementation MJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 设置每一行cell的高度
self.tableView.rowHeight = 80;
}
/**
* 隐藏状态栏
*/
- (BOOL)prefersStatusBarHidden
{
return YES;
}
/**
* 数据的懒加载
*/
- (NSArray *)tgs
{
if (_tgs == nil) {
// 初始化
// 1.获得plist的全路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"tgs.plist" ofType:nil];
// 2.加载数组
NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
// 3.将dictArray里面的所有字典转成模型对象,放到新的数组中
NSMutableArray *tgArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
// 3.1.创建模型对象
MJTg *tg = [MJTg tgWithDict:dict];
// 3.2.添加模型对象到数组中
[tgArray addObject:tg];
}
// 4.赋值
_tgs = tgArray;
}
return _tgs;
}
#pragma mark - 数据源方法
/**
* 一共有多少行数据(因为只有一组所以不用写有多少组的那个方法 因为默认情况下(不写)就只有一组
*/
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tgs.count;
}
/**
* 每一行显示怎样的cell
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1. 通过一个tableView来创建一个cell
MJTgCell *cell = [MJTgCell cellWithTableView:tableView];
// 2.给cell传递模型数据
cell.tg = self.tgs[indexPath.row];
return cell;
}
@end