其实我写这个也是没办法之前用的第三方的比如 Forkingdog 、SDLayout . 但是都存在一定的不友好的地方,使用SDLayout的话有些约束会感觉和Masonry使用起来差了一大截,然而最关键的问题还是流畅问题。但是我选择使用了 Forkingdog ,这个在数据量小的时候还没发现什么问题后来数据超过几十个以后 如果在cell 使用
[tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
会直接卡死,怎么办?这时候想到了系统的预估高度,但是使用起来蹦来蹦去的。找到了网上的代码 但是都是用xib 做的 我觉得如果可以配合 Masonry 就最好不过了,经过使用发现完全可以使用的,而且和 Forkingdog 配合 Masonry 一样 瞬间脸上笑开了花!而且顺畅程度也好了,不卡主线程了。
牛X吹完了上世纪的代码:
首先是ViewController 里面的代码
#import "ViewController.h"
#import "Masonry.h"
#import "DetailTableViewCell.h"
@interface ViewController ()
<UITableViewDelegate,
UITableViewDataSource>
//预估高度缓存
@property (nonatomic,strong)NSMutableDictionary *cellAutoHeightCache;
@property (nonatomic,strong)UITableView *mytableView;
@property (nonatomic,strong)NSMutableArray *dataSource;
@end
@implementation ViewController
#pragma mark ========== 关键的方法要出现了 ==============
//=========== 关键缓存预估部分的方法 ========= 剩余的就是cell 部分的了
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
//关键的缓存在这里写
NSNumber *height = @(cell.frame.size.height);
NSString *key = [NSString stringWithFormat:@"%@_%@",indexPath,@(tableView.tag)];
[self.cellAutoHeightCache setObject:height forKey:key];
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//如果我们需要在一个控制器内设置两个不同的tableView 的时候这时候我们就需要设置tableView 的tag值
NSString *key = [NSString stringWithFormat:@"%@_%@",indexPath,@(tableView.tag)];
NSNumber *height = [self.cellAutoHeightCache objectForKey:key];
if(height) {
return height.floatValue;
} else {
return 44.0f;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
//=========== 关键部分的方法 =========
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTranslucent:NO];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.mytableView];
//约束
[_mytableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
_mytableView.estimatedRowHeight = 44.0f;
_mytableView.rowHeight = UITableViewAutomaticDimension;
self.mjTableView = _mytableView;
_mytableView.delegate = self;
_mytableView.dataSource = self;
[_mytableView registerClass:[DetailTableViewCell class] forCellReuseIdentifier:@"detailCell"];
[self isPullDown:YES andIsPullUp:YES];
[self begainRefresh];
}
#pragma mark 上拉加载更多
-(void)pullUpMore
{
[super pullUpMore];
__weak typeof(self)ws = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[ws addDataSource];
});
});
}
#pragma mark 下拉刷新
-(void)pullDownRefresh
{
[super pullDownRefresh];
__weak typeof(self)ws = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[ws.dataSource removeAllObjects];
[ws addDataSource];
});
});
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataSource.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"detailCell";
DetailTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.model = self.dataSource[indexPath.row];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return nil;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return nil;
}
#pragma mark 构建数据
-(void)addDataSource
{
NSDictionary *dataDic = @{@"name":@"张三",@"containt":@"6月29日,河北省石家庄市人民政府网站发布《石家庄市人民政府办公厅关于进一步推进商业服务业用房去库存的意见》显示,结合石家庄商业办公用房库存较多,消化周期较长的现状,将加大商业用房去库存力度,具体措施包括:降低商服用地供应总量,对调查数据显示商业服务业用房库存较大、消化周期较长的区域,及时根据调查结果确定新建项目中的商业服务业用地比例,按程序调整用地性质。文件称,对于调查数据明确商业服务业用房库存较大、消化周期较长的区域,在满足环保、日照、公共设施配套等相关要求的前提下,允许商业服务业设施用地申请调整为居住或其他用地性质,并结合控规动态维护方案合理确定调整比例,调整为居住用地的比例最高不应超过原规划商业服务业设施用地面积的70%。调整后,国土部门相应调整土地出让金。",@"imgs":@[@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530368087679&di=1e3d9331dcd1190628c6c0e1c6293154&imgtype=0&src=http%3A%2F%2Fpic31.nipic.com%2F20130704%2F7447430_092111613000_2.jpg",@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530368160910&di=e31865c755f1a9a1ac8236459c3f25c0&imgtype=0&src=http%3A%2F%2Fpic23.nipic.com%2F20120814%2F5914324_155903179106_2.jpg",@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530368160910&di=e31865c755f1a9a1ac8236459c3f25c0&imgtype=0&src=http%3A%2F%2Fpic23.nipic.com%2F20120814%2F5914324_155903179106_2.jpg"]};
NSDictionary *dataDic2 = @{@"name":@"李四",@"containt":@"6月29日,河北省石家庄市人民政府网站发布《石家庄市人民政府办公厅关于进一步推进商业服务业用房去库存的意见》显示,结合石家庄商业办公用房库存较多,消化周期较长的现状,将加大商业用房去库存力度,具体措施包括:降低商服用地供应总量,对调查数据显示商业服务业用房库存较大、消化周期较长的区域,及时根据调查结果确定新建项目中的商业服务业用地比例,按程序调整用地性质。文件称,对于调查数据明确商业服务业用房库存较大、消化周期较长的区域,在满足环保、日照、公共设施配套等相关要求的前提下,允许商业服务业设施用地申请调整为居住或其他用地性质,并结合控规动态维护方案合理确定调整比例,调整为居住用地的比例最高不应超过原规划商业服务业设施用地面积的70%。调整后,国土部门相应调整土地出让金",@"imgs":@[@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530368087679&di=1e3d9331dcd1190628c6c0e1c6293154&imgtype=0&src=http%3A%2F%2Fpic31.nipic.com%2F20130704%2F7447430_092111613000_2.jpg",@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1530368160910&di=e31865c755f1a9a1ac8236459c3f25c0&imgtype=0&src=http%3A%2F%2Fpic23.nipic.com%2F20120814%2F5914324_155903179106_2.jpg"]};
NSDictionary *dataDic3 = @{@"name":@"李四",@"containt":@"6月29日,河北省石家庄市人民政府网站发布《石家庄市人民政府办公厅关于进一步推进商业服务业用房去库存的意见》显示,结合石家庄商业办公用房库存较多,消化周期较长的现状,将加大商业用房去库存力度,具体措施包括:降低商服用地供应总量,对调查数据显示商业服务业用房库存较大、消化周期较长的区域,及时根据调查结果确定新建项目中的商业服务业用地比例,按程序调整用地性质。文件称,对于调查数据明确商业服务业用房库存较大、消化周期较长的区域,在满足环保、日照、公共设施配套等相关要求的前提下,允许商业服务业设施用地申请调整为居住或其他用地性质,并结合控规动态维护方案合理确定调整比例,调整为居住用地的比例最高不应超过原规划商业服务业设施用地面积的70%。调整后,国土部门相应调整土地出让金",@"imgs":@[]};
for (int i = 0; i<8; i++) {
[self.dataSource addObject:dataDic];
[self.dataSource addObject:dataDic2];
[self.dataSource addObject:dataDic3];
}
[self.mytableView reloadData];
[self endRefresh];
}
#pragma mark getter
-(UITableView *)mytableView
{
if (!_mytableView)
{
_mytableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped];
}
return _mytableView;
}
-(NSMutableArray *)dataSource
{
if (!_dataSource)
{
_dataSource = [[NSMutableArray alloc]init];
}
return _dataSource;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
- 我的控制器继承了父类BaseViewController 基本上是一些下拉刷新和上拉加载的,主要看缓存和返回高度部分
下面是cell 内部如何写了.其实写这个cell 最关键的就是自上而下完美高度约束,以及最关键的要确定以谁为底部约束
#import "DetailTableViewCell.h"
#import "Masonry.h"
#import "UIImageView+WebCache.h"
#define scaleX1 MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)/375.0f
#define px_scale(x) (x)/2.0f*scaleX1
#define ScreenW [UIScreen mainScreen].bounds.size.width
@implementation DetailTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
[self setUpUI];
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
[self setUpUI];
}
return self;
}
-(void)setUpUI
{
[self.contentView addSubview:self.containtLable];
[self.contentView addSubview:self.imgBgView];
[self imgBgViewAddSubV];
[_containtLable mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(px_scale(30.0f));
make.right.mas_equalTo(px_scale(-30.0f));
make.top.mas_equalTo(px_scale(30.0f));
make.height.mas_equalTo(0);
}];
[_imgBgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.containtLable.mas_bottom).offset(px_scale(30.0f));
make.height.mas_equalTo(px_scale(180.0f));
make.left.mas_equalTo(px_scale(30.0f));
make.right.mas_equalTo(px_scale(30.0f));
//这里是最关键的一句!!!!!
make.bottom.equalTo(self.contentView.mas_bottom).offset(-30.0f);
}];
}
#pragma mark 继承了父类的方法 直接使用就行
-(void)configerModel:(id)model
{
if ([model isKindOfClass:[NSDictionary class]]) {
//是字典 类型ok
NSDictionary *dic = model;
NSString *title = dic[@"containt"];
NSArray *imgs = dic[@"imgs"];
_containtLable.text = title;
CGSize textSize = [_containtLable sizeThatFits:CGSizeMake(ScreenW-px_scale(60), CGFLOAT_MAX)];
[_containtLable mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(textSize.height);
}];
[self configerImages:imgs];
}
}
-(void)configerImages:(NSArray *)images
{
BOOL isShow = YES;
if (images.count==0) {
isShow = NO;
}else{
isShow = (images.count>0)?YES:NO;
}
[_imgBgView mas_updateConstraints:^(MASConstraintMaker *make) {
if (isShow) {
make.height.mas_equalTo(px_scale(180.0f));
make.top.equalTo(self.containtLable.mas_bottom).offset(px_scale(30.0f));
}else{
make.height.mas_equalTo(0);
make.top.equalTo(self.containtLable.mas_bottom).offset(0);
}
}];
if (isShow) {
for (int i = 0; i<3; i++) {
UIImageView *imgV = [_imgBgView viewWithTag:(100+i)];
if (i<images.count) {
imgV.hidden = NO;
[imgV sd_setImageWithURL:[NSURL URLWithString:images[i]]];
}else{
imgV.hidden = YES;
imgV.image = nil;
}
}
}
}
-(void)imgBgViewAddSubV
{
CGFloat space = px_scale(4);
CGFloat imgWidth =(ScreenW-px_scale(30*2)-space*2)/3.0f;
UIImageView *lastImageView = nil;
for (int i = 0; i<3; i++) {
UIImageView *imgV = [UIImageView new];
imgV.contentMode = UIViewContentModeScaleAspectFill;
imgV.clipsToBounds = YES;
imgV.tag = 100+i;
imgV.backgroundColor = [UIColor lightGrayColor];
[_imgBgView addSubview:imgV];
[imgV mas_makeConstraints:^(MASConstraintMaker *make) {
if (!lastImageView) {
make.left.mas_equalTo(0);
}else{
make.left.equalTo(lastImageView.mas_right).offset(space);
}
make.top.and.bottom.mas_equalTo(0);
make.width.mas_equalTo(imgWidth);
}];
lastImageView = imgV;
}
}
-(UIView *)imgBgView
{
if (!_imgBgView)
{
_imgBgView = [[UIView alloc]init];
}
return _imgBgView;
}
-(UILabel *)containtLable
{
if (!_containtLable)
{
_containtLable = [[UILabel alloc]init];
_containtLable.numberOfLines = 0;
_containtLable.font = [UIFont systemFontOfSize:14.0f];
_containtLable.textColor = [UIColor blackColor];
}
return _containtLable;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
- 敲黑板:考试要考的
- 如果觉得可以或者想要demo的朋友
- 请加QQ群 :
- 637387838
- 欢迎骚扰!
https://github.com/lanligang/forkingDogDemo
网友评论