先创建一个UITableViewCell的xib
#import "MyTableViewCell.h"
#import <UIKit/UIKit.h>
@interface MyTableViewCell : UITableViewCell
- (IBAction)clickMeBtn:(UIButton *)sender;
@property (copy, nonatomic) void(^touchClickButton)();
@end
#import "MyTableViewCell.h"
@implementation MyTableViewCell
- (void)awakeFromNib {
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
//定制UITableViewCell的事件响应处理
- (IBAction)clickMeBtn:(UIButton *)sender {
if (self.touchClickButton) {
self.touchClickButton();
}
}
@end
对UITabeView基本用法的总结
#import "ViewController.h"
#import "MyTableViewCell.h"
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic , strong) UITableView * tableView;
@property (nonatomic , assign) NSInteger index;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self tableView];
}
#pragma mark - 设置cell分割线靠右
-(void)viewDidLayoutSubviews {
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPat{
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
[cell setSeparatorInset:UIEdgeInsetsZero];
}
}
#pragma mark - UITableViewDelegate
//section的header view 的高度。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 64;
}
//section的footer view 的高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.1;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - UITableViewDataSource
//返回分区数(默认为1)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 6;
}
//返回每个分区头部的标题和尾部标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;{
return @"每个分区头部的标题";
}
//设置自定义头视图和尾视图--当然,我们可以通过self.tableView.tableHeaderView = [UIView alloc] init];这种方式来自定义headerView,但是这种方式会使tableView中所有的headerView都一样,如果我们想让每一组的headerView不一样只能使用代理方法。
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;{
UIView * view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 20)];
view.backgroundColor = [UIColor yellowColor];
return view;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;//显示箭头
//cell.selectionStyle = UITableViewCellSelectionStyleNone;//点击没有效果
//点击cell里的button执行的事件
__weak typeof(self)weakSelf = self;
[cell setTouchClickButton:^{
weakSelf.index = indexPath.row;
NSLog(@"你点击的是第%ld",(long)weakSelf.index);
}];
return cell;
}
#pragma mark - lazyloading
- (UITableView *)tableView {
if(_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
_tableView.delegate = self;
_tableView.dataSource = self;
//设置cell的自适应高度
_tableView.estimatedRowHeight = 44;//预计高度为44
_tableView.rowHeight = UITableViewAutomaticDimension;//自适应高度
//_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;//不显示分割线
[_tableView registerNib:[UINib nibWithNibName:@"MyTableViewCell" bundle:nil] forCellReuseIdentifier:@"MyTableViewCell"];
[self.view addSubview:_tableView];
}
return _tableView;
}
//实现右滑动删除
//- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// return YES;
//}
//
//- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//
// if (editingStyle == UITableViewCellEditingStyleDelete) {
// [_array removeObjectAtIndex:indexPath.row];
// [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//
// }
// else if (editingStyle == UITableViewCellEditingStyleInsert) {
// // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
// }
//}
//- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
//{
// return @"删除";
//}
@end
在定制的UITableViewCell中,如果需要对cell中的控件添加事件响应,就要想办法把cell的indexPath传递给响应函数,在此总结了比较常用的代理方法,希望对大家有帮助。
效果图如下
cell的高度返回
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
return cell.frame.size.height;
加好约束后,然后告诉tableView自己去适应高度就可以了。有两种写法:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 100;
但是如果我们用了自动计算高度的方法,又调用了tableView的reloadData方法(例如我们的数据有分页的时候,加载完下一页的数据后会去刷新tableView)。这时候就会出现问题,点击状态栏就有几率不能精确滚动到顶部了:
解决这个问题的办法是去缓存cell的高度,代码如下:
@property (nonatomic, strong) NSMutableDictionary *heightAtIndexPath;//缓存高度所用字典
#pragma mark - UITableViewDelegate
-(CGFloat)tableView:(UITableView *)tableViewestimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *height = [self.heightAtIndexPathobjectForKey:indexPath];
if(height)
{
return height.floatValue;
}
else
{
return 100;
}
}
- (void)tableView:(UITableView *)tableViewwillDisplayCell:(UITableViewCell *)cellforRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *height = @(cell.frame.size.height);
[self.heightAtIndexPathsetObject:heightforKey:indexPath];
}
解释一下,就是用一个字典做容器,在cell将要显示的时候在字典中保存这行cell的高度。然后在调用estimatedHeightForRowAtIndexPath方法时,先去字典查看有没有缓存高度,有就返回,没有就返回一个大概高度。
滚到最后一行
[self.tableView scrollToRow:[_recordCollection count] - 1 inSection:0 atScrollPosition:UITableViewScrollPositionBottom animated:YES];
获取当前cell
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:0 inSection:0];
AddFriendsDefaultCell * cell = [self.tableView cellForRowAtIndexPath:indexpath];
ios - 原生骨架屏,网络加载过渡动画的封装https://www.tuicool.com/articles/eMnmU3B
优化点1:cellForRowAtIndexPath
主要思路是减少cellForRowAtIndexPath 方法中的运算量,从以下方面检查
1.1 加载图片时,做异步处理,加载完成后再单独更新cell,不要用reloadData刷新数据。
1.2 图片有变换时,提前调整图片尺寸,并做缓存,刷新时直接取缓存图片。
1.3 优先使用CALayer绘制Cell,避免继承UITableViewCell,覆盖drawRect,因为cell除了contentView外,还有其他视图,会导致叠加运算。
1.4 复杂数据提前计算并缓存。
优化点2:heightForRowAtIndexPath
主要思路是减少高度的计算时间,有以下方法:
2.1 如果都是固定cell高度,不要显式实现代理 heightForRowAtIndexPath,使用 rowHeight属性设置固定值。
2.2 非固定高度,提前计算并缓存,刷新时直接取缓存高度值。
2.3 总是通过estimatedHeightForRowAtIndexPath 返回估计高度,避免非显示cell请求高度。