// 退出键盘 思路:让控制器所管理的UIView结束编辑
[self.view endEditing:YES];
自定义cell
(1)使用系统提供给的单元格(加载数据)
1、查看要写的文件
2、写入pilst
3、通过 每样东西的键值对都是4个,用一个模型来描述
4、在Models建立一个XHLGoods模型
5、根据plist 向XHLGoods模型中添加属性(有几个就添加几个)
6、在XHLGoods.h 声明两个方法
- (instancetype) initWithDict:(NSDictionary *)dict;
+ (instancetype) goodsWithDict:(NSDictionary *)dict;
7、在XHLGoods.m 实现两个方法 模型写好之后懒加载数据
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+ (instancetype)goodsWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
8、在XHLViewController.m 中懒加载数据 声明一个属性 用来保存模型中的数据
@property (nonatomic, strong) NSArray *goods;
#pragma marl - 懒加载数据 重写get方法
- (NSArray *)goods
{
if (_goods == nil) {
//1、拿到Plist文件路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"Property List" ofType:nil];
//2、接收最外一层大叔组(数组里面存的是字典)
NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
//3、字典转模型
NSMutableArray *arrayModels = [NSMutableArray array];
//4、用字典 遍历数组里面的字典
for (NSDictionary *dict in arrayDict) {
//访问不到模型 导入模型。h
XHLGoods *model = [XHLGoods goodsWithDict:dict];
//模型全部加载到arrayModels
[arrayModels addObject:model];
}
_goods = arrayModels;
}
return _goods;
}
9、创建TableView 实现 TableView数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//1、获取模型数据
//2、创建单元格
//3、把模型数据设置给单元格
//4、返回单元格
}
#pragma mark - 隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
return YES;
}
(2)自定义cell
10、自定义cell的两种实现方式
通过xib
1>当每个cell中的内容是固定的时候,控件个数、位置、尺寸等都一样的时候 可以使用xib加载
在Views里面创建一个名叫XHLGoodsCell的xib
通过自己写代码的方式来实现
2>每个Cell的结构不一样,每个Cell中的控件个数、样式都不一样的时候
8.通过xib方式实现自定义cell
8.1>创建一个XHLGoodsCell的xib文件
8.2>在xib中拖一个UITableViewCell,设置高度为80,宽度为屏幕宽度
8.3>向UITableViewCell中拖子控件
*拖一个UIImageView 到Cell中,设置里面的图片框的大小为 80 * 60 x=10, y= 10
*拖一个标题Label
*拖一个价格Label
//通过xib的方式来创建单元格 当我们创建单元格时,指定重用ID通过xib来指定
XHLGoodsCell *cell = [[[NSBundle mainBundle] loadNibNamed:@"XHLGoodsCell" owner:nil options:nil] firstObject];
//3、把模型数据设置给单元格
//在控制器中直接为cell的每个子控件赋值数据造成的问题
//1、控制器强依赖于cell,一旦cell内部的子控件发生了变化,那么控制器的代码也得改(这就造成了紧耦合)
//2、cell的封装不够完整,凡是用到这个cell的地方,每次都要为cell的子控件一次赋值的语句,比如cell.xxx = model.title
//3、解决办法:直接把模型传递给自定义cell,然后在自定义cell的内部解析model中的数据,赋值给自定义cell的子控件
cell.goods = model; //重写model中的setter方法
进入自定义cell重写goods的setter方法
- (void)setGoods:(XHLGoods *)goods
{
_goods = goods;
//把模型的数据设置给子控件
self.imageViewIcon.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中封装一个类方法
.h文件
+ (instancetype)goodsCellWithTableView:(UITableView *)tableView;
.m文件
+ (instancetype)goodsCellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"goods_cell"; //定义一个重用ID 根据重用ID取数据
XHLGoodsCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //从缓存中区
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:@"XHLGoodsCell" owner:nil options:nil] firstObject];
}
return cell;
}
(3)实现加载更多
//系统的TableView.tableFooterView的特性 (x,y,w,h) 只能改变x,h 不能改变y,w
//通过加载xib设置TableView.tableFooterView
XHLFooterView *footView = [[[NSBundle mainBundle] loadNibNamed:@"XHLFooterView" owner:nil options:nil] firstObject];
self.myTableView.tableFooterView = footView;
创建一个XHLFooterView.xib 里面放置一个button
在button上添加一个View 在View添加两个指示器
最开始的时候让View隐藏
当点击button是 加载更多隐藏 view显示
XHLFooterView.m
/**
* 加载更多按钮的单击事件
*
*
*/
- (IBAction)btnLoadMoreClick:(id)sender {
//1、隐藏 加载更多 按钮
self.btnLoadMore.hidden = YES;
//2、显示 等待指示器 所在的哪个View
self.waitingView.hidden = NO;
//3、增加一条数据
//4、刷新UITableView
}
等待指示器默认不旋转 设置它的属性Animating 默认不执行动画 Hides When Stopped 停止就隐藏
XHLFooterView不能直接调用model数据 所以的使用代理 让控制器(ViewController)帮助它实现
在XHLFooterView.h中
@class XHLFooterView;
@protocol XHLFooterViewDelegate <NSObject>
@required
- (void)footerViewUpdateData:(XHLFooterView *)footerView;
@end
@property (nonatomic, weak) id<XHLFooterViewDelegate> delegate;
XHLFooterView.m中
//调用代理方法实现下面的功能
//调用footerViewUpdateData 方法之前,为了保证调用不除错,所以的先判断代理对象是否实现了这个方法,如果实现了这个方法再调用,否则不调用
if ([self.delegate respondsToSelector:@selector(footerViewUpdateData:)]) {
//3、增加一条数据
//3、1 创建一个模型对象
//3、2 把模型对象加到控制器的goods集合当中
//4、刷新UITableView
[self.delegate footerViewUpdateData:self];
}
然后再ViewController.m 是实现代理方法
#pragma mark -----XHLFooterView的代理方法
- (void)footerViewUpdateData:(XHLFooterView *)footerView
{
//3、增加一条数据
//3、1 创建一个模型对象
XHLGoods *model = [[XHLGoods alloc]init];
model.Title = @"红烧肉";
model.Price = @"¥20";
model.KanDian = @"国家SS景点";
model.BackGroundImage = @"小明.jpg";
//3、2 把模型对象加到控制器的goods集合当中
[self.goods addObject:model];
//4、刷新UITableView
[self.myTableView reloadData];
}
4(实现加载更多2)
把通过加载xib设置TableView.tableFooterView 的方法进行封装 降低耦合度,便于修改
XHLFooterView.h
+ (instancetype) footerView;
XHLFooterView.m
+ (instancetype)footerView
{
XHLFooterView *footView = [[[NSBundle mainBundle] loadNibNamed:@"XHLFooterView" owner:nil options:nil] firstObject];
return footView;
}
在ViewController里面 通过XHLFooterView的类方法进行调用
在XHLFooterView.m 中
//当这个方法被执行的时候表示XHLFooterView已经从xib中创建号了,那么意味着XHLFooterView中的子控件也被创建号,所以可以使用scrollView
- (void)awakeFromNib //控件已经从xib中唤醒
{
//在这里就表示 XHLFooterView 已经从xib中创建好了
//self.scrollView.contentSize = ..;
}
3、//根据label中文字的内容 ,来动态计算高和宽
* 根据昵称的文字计算昵称label的宽和高
**影响昵称Label的高和宽的因素:字体大小、文字多少、高度取决于是否固定了宽度(是否显示了最大的宽度和高度)
**[字符串对象 boundingRectWithSize:CGSizeMake(MAXFKIAT,MAXFLOAT) options:NSStringDrawingUsesLineFragmentOriattributes:@{NSFontAttributeName:font} context:nil];
** 保证这里计算的时候使用的字体大小和创建Label时设置的字体大小一致,使用一个宏来统一设置
** 根据昵称Label的宽和高,计算x和y
4、计算good头像的 Frame
goodW = 15;
goodH = 15;
5 、 计算正文的Label的frame
* 封装一个根据字符串计算size的方法
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize;
**注意 限制正文的宽度为355,然后 高度不限制
** 现在在viewDidLoad中暂时修改行高300,然后查看效果
** 设置Label中的文字可以换行(numberOfLines = 0 表示允许换行显示)