由UITableView缓存机制引起的崩溃问题

最近一直没有更新文章,没有别的理由就是自己懒,回头想想这几天忙着撕逼几天下来扣字过万,怎么会没有写一篇总结文章的功夫呢?

这里说说我在开发中遇到的2个由于缓存机制引起的崩溃问题:
一、在二级页面发送通知更新一级页面数据列表并执行返回一级页面时引起崩溃;
二、使用UISearchController搜索,全部数据和搜索结果公用一个UITableView,在开始搜索的时候引起崩溃。

问题一:

1
2
[[NSNotificationCenter defaultCenter]postNotificationName:FINISHARRIVALEQUIP object:nil];
[self.navigationController popViewControllerAnimated:YES];

起初猜测是发送通知又多个页面刷新,数据导致主线程堵塞引起崩溃呢,运行代码后,直接发现是数组越界引起崩溃,因为在发送通知后,直接请求数据会先清空数据源,网络请求还没有返回数据,此时刚好执行pop返回到当前页面,UITableView会直接从缓存中拿去数据,但是数据源为空。

解决方法:
1、在返回会网络请求返回数据的时候再清空数据源重新赋值
2、清空数据源后,先执行 [self.tableView reloadData]刷新列表,再执行网络请求

问题二

1
2
3
4
5
6
7
8
9
10
11
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DataSourceItem *item;
if (!_searchController.active) {
item = _dataArray[indexPath.row];
} else {
item = _searchArray[indexPath.row];
}
static NSString *cellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}

点击搜索的时候数据源切换为_searchArray,但是tableView依然按照_dataArray缓存拿去数据,从而导致崩溃。

解决方法:

1
2
3
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
[self.tableView reloadData];
}

数组越界问题

上面两种问题最终都是由于数组越界引起的崩溃,可以使用一下方法判断是否越界:

1
2
3
if (indexPath.row < _dataArray.count) {
item = [_dataArray objectAtIndex:indexPath.row];
}

不是每次都能记得加数组越界判断,我们可以使用数组的分类,在其中内部判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@interface NSArray (Util)
/*!
@method objectAtIndexCheck:
@abstract 检查是否越界和NSNull如果是返回nil
@result 返回对象
*/
- (id)objectAtIndexCheck:(NSUInteger)index;
@end
#import "NSArray+Util.h"
@implementation NSArray (Util)
- (id)objectAtIndexCheck:(NSUInteger)index
{
if (index >= [self count]) {
return nil;
}
id value = [self objectAtIndex:index];
if (value == [NSNull null]) {
return nil;
}
return value;
}
@end

总结

引起的崩溃两种情况都是数据源改变,UITableView并不知道数据源改变,还在缓存中通过IndexPath.row拿取对应数组中数据, 但此时数据源已改变,就可能会因为数组越界Carsh,以上两种情况都可以通过在改变数据源后及时刷新UITableView来解决。