您的位置:

iOS TableView全面解析

一、iOSTableView优化

iOSTableView是iOS中最重要的控件之一,而进行TableView优化是开发者必须要考虑和处理的问题。TableView优化的意义在于减小内存占用和提升性能。接下来,我们将从以下几个方面进行优化:

1、缓存高度

iOSTableView中每行高度都会被计算和更新,这将会浪费掉系统宝贵的资源。最佳的解决方法是缓存行高,这样可以提高性能并且加快TableView的滑动速度。在TableView的代理方法中通过“heightForRowAtIndexPath”方法来实现缓存高度。


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [self.cellHeightsDictionary objectForKey:indexPath];
    if (height) {
        return height.floatValue;
    } else {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:requestCellIdentifier];
        [self configureCell:cell atIndexPath:indexPath];
        [self.cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
        return cell.frame.size.height;
    }
}

2、异步图片加载

随着图片数量的增加,TableView的滑动速度也将变得越来越慢。而图片异步加载是提升TableView性能和响应速度最有效的方法。我们可以使用类似SDWebImage的第三方库进行图片异步加载。

3、减少重绘

当TableView的布局或者内容发生改变时,TableView会进行重绘,而每次重绘都会浪费掉系统的宝贵资源。因此,我们应该尽可能减少TableView的重绘次数,可以采用 lazy-loading 来实现只有在相关对象被访问时才进行数据加载。

二、iOSTableViewCell复用原理

iOSTableViewCell复用原理是iOS中最基本的机制之一。UITableView会在显示的时候自动视图中加载相应的UITableViewCell,而当UIScrollView的滚动事件触发时,需要从复用队列中取出旧的UITableViewCell然后复用它的内存空间来充当新的UITableViewCell

1、实现方法

复用UITableViewCell的方法非常简单,只需要使用dequeueReusableCellWithIdentifier:方法即可:


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellID"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellID"];
    }
    // 配置Cell...
    return cell;
}

2、注意事项

在使用dequeueReusableCellWithIdentifier:方法时,需要特别注意要使用一个可重用的cell identifier。并且,每个UICollectionViewCell的identifier必须要唯一,否则不同的UITableViewCell可能会被错误地复用。

三、iOSTableView嵌套

iOSTableView嵌套指的是UITableView中的UIViewController包含了多个UITableView,即UIViewController作为UITableView的容器。下面是实现方法:

1、实现方法

在UIViewController中创建多个UITableView,并在UITableView的代理方法中分别处理不同的业务逻辑。


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (tableView == self.tableView1) {
        return self.dataArray1.count;
    } else if (tableView == self.tableView2) {
        return self.dataArray2.count;
    }
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == self.tableView1) {
        NSArray *sectionArray = [self.dataArray1 objectAtIndex:section];
        return sectionArray.count;
    } else if (tableView == self.tableView2) {
        NSArray *sectionArray = [self.dataArray2 objectAtIndex:section];
        return sectionArray.count;
    }
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (tableView == self.tableView1) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell1ID"];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell1ID"];
        }
        // 配置Cell...
        return cell;
    } else if (tableView == self.tableView2) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell2ID"];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell2ID"];
        }
        // 配置Cell...
        return cell;
    }
    return nil;
}

2、注意事项

在使用嵌套UITableView时,需要特别注意不要在代理方法中使用hardcode,而应该通过判断UITableView的引用来做出相应的处理。

四、iOSTableView卡顿

iOSTableView卡顿通常是由于TableView中过多的Cell被加载导致的。下面是一些优化措施:

1、NSIndexPath同步

NSIndexPath的实例用来表示TableView中的行和列信息。UITableView的数据源和代理方法必须及时更新NSIndexPath的信息,否则TableView就会出现卡顿现象。

2、异步加载图片

当TableView中的Cell中包含大量的图片时,卡顿现象就会愈发明显。这是因为图片的加载是同步进行的,我们可以通过异步加载图片的方式来解决这个问题。

3、单元格重用

UITableViewCell重用是iOS中最核心的机制之一,也是优化TableView响应速度的有效方法。通过UITableViewCell的重用机制,可以大幅降低TableView卡顿的风险。

五、iOSTableView组头自定义

iOSTableView中可以自定义TableView的组头,并且可以在组头中添加按钮和文字。下面是实现方法:

1、UITableViewDelegate代理方法

可以通过UITableViewDelegate的代理方法来定制TableView的组头:


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *sectionHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.frame.size.width, 30.0f)];
    sectionHeaderView.backgroundColor = [UIColor grayColor];
    // 添加按钮和文字...
    return sectionHeaderView;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 30.0f;
}

2、注意事项

在UICollectionView中自定义组头时,需要特别注意是要使用“viewForSupplementaryElementOfKind”代理方法。

六、iOSTableView刷新一行闪动

iOSTableView刷新一行的时候会出现刷新闪动现象,这并不是iOS的Bug而是正常现象。下面是解决方法:

1、仅刷新有变化的Cell

一个常见的误解是在UITableView的reloadRowsAtIndexPaths:withRowAnimation:方法中刷新所有的Cell。实际上,这种方法只能用于更新其中有变化的UITableViewCell。UITableView会自动判断哪些行和哪些CELL发生了变化。

2、设置UIView的背景颜色

设置UITableViewCell的backgroundView或者backgroundColor属性可以避免Cell在刷新时出现闪烁现象。

七、iOSTableView卡顿的原因

1、Cell高度计算问题

当UITableView需要显示数百行,而每次行高度又需要计算时,计算过程可能会变得非常缓慢,导致UITableView卡顿。最好的解决方法是缓存UITableView的行高度。

2、图片加载问题

UITableView中的UIImageView是通过主线程同步加载的,所以当加载过多的图片时,UITableView就会卡顿。解决方法是使用异步加载图片的方式。

3、卡顿原因很多,其他原因还包括:

  • 内存泄露
  • 网络延迟
  • 复杂的视图结构
  • UITableView数据源过于庞大

要解决UITableView的卡顿问题,需要仔细分析问题并有目的地进行优化。

八、iOSTableView左滑删除带按钮选取

iOSTableView左滑删除功能是非常常见的需求,同时也可以添加按钮。下面是示例代码:


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.dataArray removeObjectAtIndex:indexPath.row];
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

- (NSArray
    *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        [self.dataArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }];
    deleteRowAction.backgroundColor=[UIColor lightGrayColor];
    UITableViewRowAction *doneRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"选中" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        NSLog(@"选中");
    }];
    doneRowAction.backgroundColor=[UIColor blueColor];
    return @[deleteRowAction,doneRowAction];
}

   

1、注意事项

在实现左滑删除功能时,需要注意不要忘记同时删除数据源中的数据。

结论

iOSTableView是iOS中最重要的控件之一,也是开发iOS应用的一个核心技术。在开发应用时,TableView的优化和高效性是绕不过的问题,要协助应用达到更高的性能水平。