app中的一个TableView,使用原生的UILocalizedIndexedCollation进行索引排序(A-Z),实测速度很慢,400多条数据需要3秒多才能显示出来,本文介绍优化的思路
定位后发现,瓶颈不在数据库访问和UI渲染上,就是索引排序太慢。优化前有性能问题的代码如下:
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 29 30
| // slow method -(void) assembleMembers:(NSArray*)origin { [members removeAllObjects];
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
// slow point 1: takes 1.5 seconds when 400 records for (Member *member in origin) { NSInteger sect = [collation sectionForObject:member collationStringSelector:@selector(name)]; member.sectionNumber = sect; }
NSInteger highSection = [[collation sectionTitles] count]; NSMutableArray *sectionArrays = [NSMutableArray arrayWithCapacity:highSection]; for (int i = 0; i < highSection; i++) { NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:1]; [sectionArrays addObject:sectionArray]; }
for (Member *member in origin) { [(NSMutableArray*)[sectionArrays objectAtIndex:member.sectionNumber] addObject:member]; }
// slow point 2: takes 1.3 seconds when 400 records for (NSMutableArray *sectionArray in sectionArrays) { NSArray *sortedSection = [collation sortedArrayFromArray:sectionArray collationStringSelector:@selector(name)]; [members addObject:sortedSection]; } }
|
有2段很慢,第一段是给Member分配sectionNumber,第二段是对26个子数组进行深度排序
发现了瓶颈,就针对瓶颈进行优化
分配sectionNumber的逻辑,放到每次插入数据库时。在表中增加section_number字段,保存这个值。这样每次从数据库取到的数据,就不需要在运行时排序了
深度排序耗时长的问题,改成首字母排序,速度也快了很多
最后的代码如下:
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
| -(void) assembleMembers:(NSArray*)origin { [members removeAllObjects];
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
NSInteger highSection = [[collation sectionTitles] count]; NSMutableArray *sectionArrays = [NSMutableArray arrayWithCapacity:highSection]; for (int i = 0; i < highSection; i++) { NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:1]; [sectionArrays addObject:sectionArray]; }
for (Member *member in origin) { [(NSMutableArray*)[sectionArrays objectAtIndex:member.sectionNumber] addObject:member]; }
for (NSMutableArray *sectionArray in sectionArrays) {
[sectionArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { Member *m1 = (Member*) obj1; Member *m2 = (Member*) obj2; return [m2.name localizedCompare:m1.name]; }];
[members addObject:sectionArray]; } }
|
这样改完之后,400条数据的处理时间缩短到0.3秒,基本可以接受了