自定cell(XIB)团购思路
步骤一、先解析plist文件,创建model层数据。
- (
instancetype
)initWithDict:(
NSDictionary
*)dict
{
self = [ super init ];
if ( self ) {
[ self setValuesForKeysWithDictionary :dict];
}
return self ;
}
+ ( instancetype )tgWithDict:( NSDictionary *)dict
{
return [[ self alloc ] initWithDict :dict];
}
+ ( NSMutableArray *)tgs
{
NSArray *array = [ NSArray arrayWithContentsOfFile :[[ NSBundle mainBundle ] pathForResource : @"tgs.plist" ofType : nil ]];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
[arrayM addObject :[ self tgWithDict :dict]];
}
return arrayM;
}
{
self = [ super init ];
if ( self ) {
[ self setValuesForKeysWithDictionary :dict];
}
return self ;
}
+ ( instancetype )tgWithDict:( NSDictionary *)dict
{
return [[ self alloc ] initWithDict :dict];
}
+ ( NSMutableArray *)tgs
{
NSArray *array = [ NSArray arrayWithContentsOfFile :[[ NSBundle mainBundle ] pathForResource : @"tgs.plist" ofType : nil ]];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
[arrayM addObject :[ self tgWithDict :dict]];
}
return arrayM;
}
二、
自定义
Cell
1
>
创建
XIB
文件,并设置控件内部细节。
2 > 创建一个与 XIB 同名的类,注意自定义的类继承自的对象,要与 XIB 中根对象的类保持一致。
3 > 重新指定 XIB 中的根类,打开助理编辑器辅助观察变化。
4 > 对需要修改属性的控件做 IBOutlet 连线,注意,不要与 TableViewCell 的已经存在的属性重名
连线控件的名称不能是:
( 1 ) textLabel
( 2 ) detailTextLabel
( 3 ) imageView
2 > 创建一个与 XIB 同名的类,注意自定义的类继承自的对象,要与 XIB 中根对象的类保持一致。
3 > 重新指定 XIB 中的根类,打开助理编辑器辅助观察变化。
4 > 对需要修改属性的控件做 IBOutlet 连线,注意,不要与 TableViewCell 的已经存在的属性重名
连线控件的名称不能是:
( 1 ) textLabel
( 2 ) detailTextLabel
( 3 ) imageView
+ (
instancetype
)cellWithTableView:(
UITableView
*)tableView
{
// 1. 可重用标示符
static NSString *ID = @"Cell" ;
// 2. tableView 查询可重用 Cell
HMTgCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
// 3. 如果没有可重用 cell
if (cell == nil ) {
NSLog ( @" 加载 XIB" );
// 从 XIB 加载自定义视图
cell = [[[ NSBundle mainBundle ] loadNibNamed : @"HMTgCell" owner : nil options : nil ] lastObject ];
}
return cell;
}
- ( void )setTg:( HMTg *)tg
{
// setter 方法中,第一句要赋值,否则要在其他方法中使用模型,将无法访问到
_tg = tg;
self . titleLabel . text = tg. title ;
self . iconView . image = [ UIImage imageNamed :tg. icon ];
self . priceLabel . text = tg. price ;
self . buyCountLabel . text = tg. buyCount ;
}
#pragma mark - 模板提供的方法
/**
初始化方法
使用代码创建 Cell 的时候会被调用,如果使用 XIB 或者 Storyboard ,此方法不会被调用
*/
- ( id )initWithStyle:( UITableViewCellStyle )style reuseIdentifier:( NSString *)reuseIdentifier
{
self = [ super initWithStyle :style reuseIdentifier :reuseIdentifier];
if ( self ) {
NSLog ( @"%s" , __func__);
}
return self ;
}
/**
从 XIB 被加载之后,会自动被调用,如果使用纯代码,不会被执行
*/
- ( void )awakeFromNib
{
NSLog ( @"%s" , __func__);
self . contentView . backgroundColor = [ UIColor clearColor ];
}
/**
Cell 被选中或者取消选中是都会被调用
如果是自定义 Cell 控件,所有的子控件都应该添加到 contentView 中
*/
- ( void )setSelected:( BOOL )selected animated:( BOOL )animated
{
[ super setSelected :selected animated :animated];
if (selected) {
self . contentView . backgroundColor = [ UIColor redColor ];
} else {
self . contentView . backgroundColor = [ UIColor greenColor ];
}
}
{
// 1. 可重用标示符
static NSString *ID = @"Cell" ;
// 2. tableView 查询可重用 Cell
HMTgCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
// 3. 如果没有可重用 cell
if (cell == nil ) {
NSLog ( @" 加载 XIB" );
// 从 XIB 加载自定义视图
cell = [[[ NSBundle mainBundle ] loadNibNamed : @"HMTgCell" owner : nil options : nil ] lastObject ];
}
return cell;
}
- ( void )setTg:( HMTg *)tg
{
// setter 方法中,第一句要赋值,否则要在其他方法中使用模型,将无法访问到
_tg = tg;
self . titleLabel . text = tg. title ;
self . iconView . image = [ UIImage imageNamed :tg. icon ];
self . priceLabel . text = tg. price ;
self . buyCountLabel . text = tg. buyCount ;
}
#pragma mark - 模板提供的方法
/**
初始化方法
使用代码创建 Cell 的时候会被调用,如果使用 XIB 或者 Storyboard ,此方法不会被调用
*/
- ( id )initWithStyle:( UITableViewCellStyle )style reuseIdentifier:( NSString *)reuseIdentifier
{
self = [ super initWithStyle :style reuseIdentifier :reuseIdentifier];
if ( self ) {
NSLog ( @"%s" , __func__);
}
return self ;
}
/**
从 XIB 被加载之后,会自动被调用,如果使用纯代码,不会被执行
*/
- ( void )awakeFromNib
{
NSLog ( @"%s" , __func__);
self . contentView . backgroundColor = [ UIColor clearColor ];
}
/**
Cell 被选中或者取消选中是都会被调用
如果是自定义 Cell 控件,所有的子控件都应该添加到 contentView 中
*/
- ( void )setSelected:( BOOL )selected animated:( BOOL )animated
{
[ super setSelected :selected animated :animated];
if (selected) {
self . contentView . backgroundColor = [ UIColor redColor ];
} else {
self . contentView . backgroundColor = [ UIColor greenColor ];
}
}
三、在控制器实现
UITableView的代理方法
#pragma mark -
数据源方法
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . tgs . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
// 1. 创建 cell
HMTgCell *cell = [ HMTgCell cellWithTableView :tableView];
// 2. 通过数据模型,设置 Cell 内容,可以让视图控制器不需要了解 cell 内部的实现细节
cell. tg = self . tgs [indexPath. row ];
return cell;
}
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . tgs . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
// 1. 创建 cell
HMTgCell *cell = [ HMTgCell cellWithTableView :tableView];
// 2. 通过数据模型,设置 Cell 内容,可以让视图控制器不需要了解 cell 内部的实现细节
cell. tg = self . tgs [indexPath. row ];
return cell;
}
四、自定义点击开始下载XIB
+ (
instancetype
)footerView
{
return [[[ NSBundle mainBundle ] loadNibNamed : @"HMTgFooterView" owner : nil options : nil ] lastObject ];
}
- ( IBAction )loadMore
{
NSLog ( @" 加载更多 " );
// 1. 隐藏按钮
self . loadMoreButton . hidden = YES ;
// 2. 显示提示视图
self . tipsView . hidden = NO ;
// 3.1 判断代理是否实现了协议方法
if ([ self . delegate respondsToSelector : @selector (tgFooterViewDidDownloadButtonClick:)]) {
[ self . delegate tgFooterViewDidDownloadButtonClick : self ];
}
}
/** 视图控制器刷新完成调用方法 */
{
return [[[ NSBundle mainBundle ] loadNibNamed : @"HMTgFooterView" owner : nil options : nil ] lastObject ];
}
- ( IBAction )loadMore
{
NSLog ( @" 加载更多 " );
// 1. 隐藏按钮
self . loadMoreButton . hidden = YES ;
// 2. 显示提示视图
self . tipsView . hidden = NO ;
// 3.1 判断代理是否实现了协议方法
if ([ self . delegate respondsToSelector : @selector (tgFooterViewDidDownloadButtonClick:)]) {
[ self . delegate tgFooterViewDidDownloadButtonClick : self ];
}
}
/** 视图控制器刷新完成调用方法 */
在XIB添加View和Button,加载完数据之后,View隐藏,Button显示。
- ( void )endRefresh
{
// 4. 加载完成数据
self . loadMoreButton . hidden = NO ;
self . tipsView . hidden = YES ;
}
- ( void )endRefresh
{
// 4. 加载完成数据
self . loadMoreButton . hidden = NO ;
self . tipsView . hidden = YES ;
}
五、自定义协议,当点击开始下载按钮,通知控制器
@protocol
HMTgFooterViewDelegate <
NSObject
>
@optional
/** 视图的下载按钮被点击 */
- ( void )tgFooterViewDidDownloadButtonClick:( HMTgFooterView *)footerView;
@end
@optional
/** 视图的下载按钮被点击 */
- ( void )tgFooterViewDidDownloadButtonClick:( HMTgFooterView *)footerView;
@end
- (
void
)tgFooterViewDidDownloadButtonClick:(
HMTgFooterView
*)footerView
{
// 模拟取网络上获取数据加载数据
NSLog ( @" 努力加载数据中 ...." );
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 2.0 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
// 获得网络数据之后执行的操作
// 向数组中添加数据,模拟网络加载完成之后的效果
NSDictionary *dict = @{ @"title" : @" 哈哈 " , @"icon" : @"ad_00" , @"price" : @"100.2" , @"buyCount" : @"250" } ;
HMTg *tg = [ HMTg tgWithDict :dict];
NSLog ( @" 加数据前 %d" , self .tgs. count );
[ self . tgs addObject :tg];
NSLog ( @" 加数据后 %d" , self .tgs. count );
// 刷新数据
// [self.tableView reloadData];
// 新建一个 indexPath
NSIndexPath *path = [ NSIndexPath indexPathForRow :( self . tgs . count - 1 ) inSection : 0 ];
[ self . tableView insertRowsAtIndexPaths : @[ path ] withRowAnimation : UITableViewRowAnimationMiddle ];
// 通知页脚视图调整视图显示状态
[footerView endRefresh ];
});
}
{
// 模拟取网络上获取数据加载数据
NSLog ( @" 努力加载数据中 ...." );
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 2.0 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
// 获得网络数据之后执行的操作
// 向数组中添加数据,模拟网络加载完成之后的效果
NSDictionary *dict = @{ @"title" : @" 哈哈 " , @"icon" : @"ad_00" , @"price" : @"100.2" , @"buyCount" : @"250" } ;
HMTg *tg = [ HMTg tgWithDict :dict];
NSLog ( @" 加数据前 %d" , self .tgs. count );
[ self . tgs addObject :tg];
NSLog ( @" 加数据后 %d" , self .tgs. count );
// 刷新数据
// [self.tableView reloadData];
// 新建一个 indexPath
NSIndexPath *path = [ NSIndexPath indexPathForRow :( self . tgs . count - 1 ) inSection : 0 ];
[ self . tableView insertRowsAtIndexPaths : @[ path ] withRowAnimation : UITableViewRowAnimationMiddle ];
// 通知页脚视图调整视图显示状态
[footerView endRefresh ];
});
}