下面根据这些优化策略来使用代码展示

1: 尽量少的Cell的类型
当Cell的结构基本差不多时候,可以将Cell只创建一种Cell,这样Cell的体积会增大,但是Cell的数量不会有很多,
UITableViewCell的复用机制是离屏就会进入缓存池中,那么一屏可以有N个Cell,那个一种Cell的缓存数就是N+1,如果有M种Cell,那么缓存数就是M*N个.利用同一种类型的cell,去灵活利用view的hidden属性,可以很好的降低Cell的类型数量,不过依照实际需求看.
typedefenum: NSUInteger {
FriendsterCellTypeNone = -1,//错误码 不存在
FriendsterCellTypeAll =0,//default
FriendsterCellTypeImage,
FriendsterCellContent,} FriendsterCellType;
@interfaceFriendsterTableViewCell:UITableViewCell
@property(nonatomic,strong)FriendsterModel *model;//不设置照片 这个先可以不看,后面优化会用到
@property(nonatomic,strong)FriendsterModel *noImageModel;
@end
2: 提前计算Cell的高度
系统会先调用“tableView:heightForRowAtIndexPath:”获取每个Cell即将显示的高度,从而确定整个UITableView的布局。然后才调用“tableView:cellForRowAtIndexPath”获取每个Cell,我们也是在这里填充、设置Cell的。
在Model中计算并保存Cell的高度
@interfaceFriendsterModel:NSObject
@property(nonatomic,strong)NSString*icon_url;
@property(nonatomic,assign)CGRecticonF;
@property(nonatomic,strong)UIImage*iconImage;
@property(nonatomic,strong)NSString*content;
@property(nonatomic,assign)CGRectcontentF;
@property(nonatomic,strong)NSString*name;
@property(nonatomic,assign)CGRectnameF;
@property(nonatomic,strong)NSString*img_url;
@property(nonatomic,assign)CGRectimgF;
@property(nonatomic,assign)CGFloatcellHeight;
@property(nonatomic,assign)FriendsterCellType cellType;
@property(nonatomic,assign)BOOLisAnimation;
+ (instancetype)friendsterWithDict:(NSDictionary*)dict;
- (instancetype)initWithDict:(NSDictionary*)dict;
//这个方法是返回对应Cell的高度的,可以在数据层计算好每一个Cell的高度,之后直接从缓存中取出来就可以了,因为UITableView的调用之前会先把所有的Cell的高度全部获取一遍,这里就是返回高度的地方,如果在这里大量计算,会延迟TableView的加载
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
FriendsterModel *model =self.dataArray[indexPath.row];
return model.cellHeight;
}
3: 缓存展示数据
例子: 内容页有类似于富文本形式的展示类的东西,
可以将富文本在数据层处理好,缓存在数据中,展示的时候直接复制即可,不用在创建NSMutableAttributedString 来组装数据
4: 缓存展示Cell
对于一些简单的,小的View,可以缓存在数据层,用的时候直接拿出来,不用在Cell里面进行重复创建.
5: 对于不透明的View,设置opaque为YES,这样在绘制该View时,就不需要考虑被View覆盖的其他内容(尽量设置Cell的view为opaque,避免GPU对Cell下面的内容也进行绘制).
6: 尽量减少 Cell 的视图层级,可以使用异步绘制的方式,并且少用或不用透明的视图。尽量显示“大小刚好合适的图片资源”
7: 避免离屏渲染,比如同时使用
view.layer.masksToBounds= YES;
view.layer.cornerRadius=20.0;
可以用 使用CAShapeLayer和UIBezierPath设置圆角.
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100,100,100,100)];
imageView.image= [UIImage imageNamed:@"3"];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.boundsbyRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];//设置大小
maskLayer.frame= imageView.bounds;//设置图形样子
maskLayer.path= maskPath.CGPath;
imageView.layer.mask= maskLayer;
[self.viewaddSubview:imageView];
8: 快速滑动时按需加载
快滑动过程中,只加载目标范围内的Cell,这样按需加载,极大的提高流畅度。
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint*)targetContentOffset{
NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
NSIndexPath*cip = [[self indexPathsForVisibleRows] firstObject];
NSInteger skipCount = 8;
if(labs(cip.row-ip.row) > skipCount) {
NSArray*temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y,self.width,self.height)];
NSMutableArray*arr = [NSMutableArray arrayWithArray:temp];
if(velocity.y<0) {
NSIndexPath*indexPath = [temp lastObject];
if(indexPath.row+33) {
[arr addObject:[NSIndexPathindexPathForRow: indexPath.row-3 inSection: 0]];
[arr addObject:[NSIndexPathindexPathForRow: indexPath.row-2 inSection: 0]];
[arr addObject:[NSIndexPathindexPathForRow: indexPath.row-1 inSection: 0]];
}
}
[needLoadArr addObjectsFromArray:arr];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
if(needLoadArr.count>0 && [needLoadArr indexOfObject:indexPath] == NSNotFound) {
[cell clear];
return;
}
...
}
9: 图片加载优化:
当用户手动 drag table view 的时候,会加载 cell 中的图片; * 在用户快速滑动的减速过程中,不加载过程中 cell
中的图片(但文字信息还是会被加载,只是减少减速过程中的网络开销和图片加载的开销);
在减速结束后,加载所有可见 cell 的图片(如果需要的话);
/*
优化达到的效果
1: 当用户手动 drag table view 的时候,会加载 cell 中的图片;
2: 在用户快速滑动的减速过程中,不加载过程中 cell 中的图片(但文字信息还是会被加载,只是减少减速过程中的网络开销和图片加载的开销);
3: 在减速结束后,加载所有可见 cell 的图片(如果需要的话);
4: 在减速结束后,需要显示的Cell的图片要优先下载.
scrollViewWillBeginDragging 即将开始拖拽
scrollViewWillEndDragging: withVelocity: targetContentOffset: 即将停止拖拽
scrollViewDidEndDecelerating 已经停止减速
进一步优化
1: 如果内存中有图片的缓存,减速过程中也会加载该图片
2: 如果图片属于 targetContentOffset 能看到的 cell,正常加载,这样一来,快速滚动的最后一屏出来的的过程中,用户就能看到目标区域的图片逐渐加载
*/
//即将开始拖动
- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView{
NSLog(@"%s",__func__);//
_isNeedLoadImage = NO;
}
//即将停止拖动 滚动很快时,只加载目标范围内的Cell,这样按需加载,极大的提高流畅度。
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint*)targetContentOffset{
NSLog(@"%s",__func__);
// 先获取当前开始减速时第几行
NSIndexPath*ip = [self.tableView indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
NSIndexPath*cip = [[self.tableView indexPathsForVisibleRows] firstObject];
NSLog(@"%@",ip);
NSLog(@"%@",cip);
NSIntegerskipCount =6;//判断快速滑动的cell跨越的数量
if(labs(cip.row-ip.row)>skipCount) {
_isQuickScroll =YES;
}else{
_isQuickScroll =NO;
}
}
//即将开始减速- (void)scrollViewWillBeginDecelerating:(UIScrollView*)scrollView{
NSLog(@"%s",__func__);
_isDecelerationing =YES;
}
//已经停止减速
- (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{
NSLog(@"%s",__func__);
_isNeedLoadImage =YES;
_isDecelerationing =NO;
_isQuickScroll =NO;
//刷新当前屏幕可见CEll
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}
完成!!!!
网友评论