iOS Tableview优化

作者: simuty | 来源:发表于2016-06-15 15:26 被阅读1602次

    转接上篇iOS界面卡顿的原因

    第一 CPU考虑方向

    1. 对象创建;

    1.1 Tableview初始化

    #pragma 懒加载
    - (UITableView *)tableView{
        if (!_tableView) {
            _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - self.cycleScrollView2.frame.size.height)];
            _tableView.delegate = self;
            _tableView.dataSource = self;
            [self.view addSubview:_tableView];
        }
        return _tableView;
    }
    
    
    

    1.2 复用cell


    • 从 iOS 6 以后,我们在 UITableView 和 UICollectionView 中可以复用 Cell以及各个 Section 的 Header 和 Footer。

    • 确保TableviewCell/Header/Footer使用了复用机制, 而不是每一次都创建;

    @interface HomeVC ()<UITableViewDataSource, UITableViewDelegate>
    
    @property (nonatomic, strong) UITableView *tableView;
    
    @end
    
    
    static NSString *cellId = @"Cell";
    
    @implementation HomeVC
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.myTableView.delegate = self;
        self.myTableView.dataSource = self;
    //第一种注册cell<nib文件类HomeTableViewCell>
        [self.tableView registerNib:[UINib nibWithNibName:@"HomeTableViewCell" bundle:nil] forCellReuseIdentifier:cellId];
        
    //第二种注册Cell<纯手工打造的HomeVC>
    // [self.tableView registerClass:[HomeVC class]forCellReuseIdentifier:cellId];
        
    }
    
    #pragma 代理
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        //获取重用池中的cell
        HomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
        //如果没有取到,就初始化
        if (!cell) {
            cell = [[HomeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
        }
        
        cell.cellNameLab.text = @"Name";
        return cell;
    }
    
    

    1.2.1 以下为重用相关API

    // 复用 Cell:
    - [UITableView dequeueReusableCellWithIdentifier:];
    - [UITableView registerNib:forCellReuseIdentifier:];
    - [UITableView registerClass:forCellReuseIdentifier:];
    - [UITableView dequeueReusableCellWithIdentifier:forIndexPath:];
    // 复用 Section 的 Header/Footer:
    - [UITableView registerNib:forHeaderFooterViewReuseIdentifier:];
    - [UITableView registerClass:forHeaderFooterViewReuseIdentifier:];
    - [UITableView dequeueReusableHeaderFooterViewWithIdentifier:];
    
    
    

    2. TabelView 代理

    2.1 避免快速滑动情况下开过多线程。

    cell中的图片开线程异步加载<SDWebImage(异步操作)>。但是线程开过多了会造成资源浪费,内存开销过大。图片过多时可以不要一滚动就走cellForRow方法,可以在scrollview的代理方法中做限制当滚动开始减速的时候才加载显示在当前屏幕上的cell(通过tableview的dragging和declearating两个状态也能判断)

    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        //如果没有取到,就初始化
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
        }
        cell.textLabel.text = @"Name";
    
        BOOL canLoad = !self.tableView.dragging && !_tableView.decelerating;
        if  (canLoad) {
            //开始loaddata,异步加载图片
            NSLog(@"开始加载图片");
        }
        return cell;
    }
    
    
    // 滚动停止时,触发该函数
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        //刷新tableview
       // [self.tableView reloadData];
    
    
     //在此刷新的是屏幕上显示的cell的内容
        NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
        //获取到的indexpath为屏幕上的cell的indexpath
        [self.tableView reloadRowsAtIndexPaths:visiblePaths withRowAnimation:UITableViewRowAnimationRight];
    
    }
    
    
    
    3 图片圆角

    第一种方法: layer.cornerRadius

    imageView.layer.cornerRadius = imageView.frame.size.width/2.0;  
    // 隐藏边界
    imageView.layer.masksToBounds = YES;
    
    

    第二种方法: 头像使用蒙版+贝塞尔曲线加圆角

    
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.icon.width / 2, self.icon.height / 2) radius:self.icon.width / 2  startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    
    layer.path = path.CGPath;
    self.icon.layer.mask = layer;
      
    

    第三种方法:
    stackoverflow

    
        UIImageView *iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
        [self.view addSubview:iconImage];
        
        // Get your image somehow
        UIImage *image = [UIImage imageNamed:@"image.jpg"];
        // Begin a new image that will be the new image with the rounded corners
        // (here with the size of an UIImageView)
        UIGraphicsBeginImageContextWithOptions(iconImage.bounds.size, NO, [UIScreen mainScreen].scale);
        // Add a clip before drawing anything, in the shape of an rounded rect
        [[UIBezierPath bezierPathWithRoundedRect:iconImage.bounds cornerRadius:10.0] addClip];
        // Draw your image
        [image drawInRect:iconImage.bounds];
        // Get the image, here setting the UIImageView image
        iconImage.image = UIGraphicsGetImageFromCurrentImageContext();
        // Lets forget about that we were drawing
        UIGraphicsEndImageContext();
    
    

    第四种方法:

    
    
    
    
    
    
    4 异步加载图片

    第一种方法: SDWebImage的使用

    
    [imageView sd_setImageWithURL:url completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                imageView.image = image;
    }];
    
    

    5 优化UITableViewCell高度计算

    Tip

    1. 使用不透明视图, 如非必要, 可以设置opaque为yes;
    2. 图片的alpha尽量不设置透明度;
    3. cellForRowAtIndexPath不要做耗时操作, 
       * 读取文件/写入文件;
       * 尽量不要去添加和移除view;
    4.   
    
    
    
    

    参考:

    tableView性能优化

    关于性能的一些问题
    iOS中检测UIScrollView滚动动画是否结束

    更多精彩内容请关注“IT实战联盟”哦~~~


    IT实战联盟.jpg

    相关文章

      网友评论

      • 吾日三省唔:第一种注册和第二种注册cell在使用时,有什么不同没说清楚
        Mr鹏先生:注释那么清楚。。。。。

      本文标题:iOS Tableview优化

      本文链接:https://www.haomeiwen.com/subject/trhpdttx.html