我有一个循环通过相当大量的物体的环形循环(目前4000多个,但可能是双倍且不断增长。)
我尝试加速循环,我能够使用自动释放池释放内存并避免应用程序崩溃,但就速度而言,循环非常慢。
有人建议我使用有序数组,但我对编程很新,所以我有点迷失。有人可以分享一些指示吗?
对象" Sede"有渐进ID
这是我的代码:
NSArray *sedi = [Sede sedeArray];
for (Sede *sedeTmp in sedi)
{
@autoreleasepool {
if (sedeTmp.idSede == idSede)
{
sede = sedeTmp;
break;
}
}
}
这是我的完整代码:
+ (void)importData:(NSDictionary *)data
{
NSArray *info = data[@"Info"];
if (info != (id)[NSNull null])
{
}
NSMutableArray *utenti = [NSMutableArray arrayWithArray:[Utente utenteArray]];
NSMutableArray *utentiNew = [[NSMutableArray alloc] init];
for (NSDictionary *utenteWS in data[@"Utenti"])
{
NSInteger stato = [(NSNumber *)[NSString decrypt:utenteWS[@"Stato"]] integerValue];
NSInteger idUtente = [(NSNumber *)[NSString decrypt:utenteWS[@"IDUtente"]] integerValue];
Utente *utente = nil;
for (Utente *utenteTmp in utenti)
{
if (utenteTmp.idUtente == idUtente)
{
utente = utenteTmp;
break;
}
}
if (stato == 2) //DELETE
{
if (utente)
{
[self setUtente:utente fromUtenteWS:utenteWS];
utente.eliminato = YES;
}
continue;
}
if (!utente)
{
utente = [Utente utente:(int)idUtente];
[utentiNew addObject:utente];
}
[self setUtente:utente fromUtenteWS:utenteWS];
}
[BOTManagedObjectContext save];
[utenti addObjectsFromArray:utentiNew];
NSArray *sedi = [Sede sedeArray];
NSMutableArray *sediDel = [[NSMutableArray alloc] init];
NSMutableArray *contattiDel = [[NSMutableArray alloc] init];
for (NSDictionary *sedeWS in data[@"Sedi"])
{
NSInteger statoSede = [(NSNumber *)[NSString decrypt:sedeWS[@"Stato"]] integerValue];
long long idSede = [(NSNumber *)[NSString decrypt:sedeWS[@"IDSede"]] longLongValue];
Sede *sede = nil;
NSArray *sedeArray = [Sede sedeArray];
NSMutableDictionary *itemsByItemID = [NSMutableDictionary dictionary];
for (Sede *sede in sedeArray) {
itemsByItemID[@(sede.idSede)] = sede;
}
self.sedesBySedeID = itemsByItemID;
//for loop is too slow
/*for (Sede *sedeTmp in sedi)
{
@autoreleasepool {
if (sedeTmp.idSede == idSede)
{
sede = sedeTmp;
break;
}
}
}*/
//end of guilty for loop
if (!sede)//if enters here, local db is empty
{
if (statoSede == 2) //DELETE
continue;
sede = [BOTManagedObjectContext insertNewObjectForEntityForName:@"Sede"];
sede.idSede = idSede;
NSInteger idUtente = [(NSNumber *)[NSString decrypt:sedeWS[@"IDUtente"]] integerValue];
for (Utente *utente in utenti)
{
if (utente.idUtente == idUtente)
{
sede.utente = utente;
break;
}
}
for (NSDictionary *contattoWS in sedeWS[@"Contatti"])
{
if ([(NSNumber *)[NSString decrypt:contattoWS[@"Stato"]] integerValue] == 2) continue;
Contatto *contatto = [BOTManagedObjectContext insertNewObjectForEntityForName:@"Contatto"];
contatto.sede = sede;
[self setContatto:contatto fromContattoWS:contattoWS];
}
[self setSede:sede fromSedeWS:sedeWS];
}
else
{
if (statoSede == 2 && !sede.tour) //DELETE
{
[sediDel addObject:sede];
for (Contatto *contatto in sede.contattoCollection)
{
[contattiDel addObject:contatto];
}
continue;
}
for (NSDictionary *contattoWS in sedeWS[@"Contatti"])
{
NSInteger statoContatto = [(NSNumber *)[NSString decrypt:contattoWS[@"Stato"]] integerValue];
BOOL find = NO;
long long idContatto = [(NSNumber *)[NSString decrypt:contattoWS[@"IDContatto"]] longLongValue];
for (Contatto *contatto in sede.contattoCollection)
{
if (contatto.idContatto == idContatto)
{
find = YES;
if (statoContatto == 2) //DELETE
{
[contattiDel addObject:contatto];
}
else
{
[self setContatto:contatto fromContattoWS:contattoWS];
}
break;
}
}
if (!find)
{
if (statoContatto == 2) //DELETE
continue;
Contatto *contatto = [BOTManagedObjectContext insertNewObjectForEntityForName:@"Contatto"];
contatto.sede = sede;
[self setContatto:contatto fromContattoWS:contattoWS];
}
}
//controllo se ci sono contatti non presenti nel ws e in caso li elimino
for (Contatto *contatto in sede.contattoCollection)
{
BOOL find = NO;
for (NSDictionary *contattoWS in sedeWS[@"Contatti"])
{
long long idContatto = [(NSNumber *)[NSString decrypt:contattoWS[@"IDContatto"]] longLongValue];
if (contatto.idContatto == idContatto)
{
find = YES;
break;
}
}
if (!find)
{
[contattiDel addObject:contatto];
}
}
[self setSede:sede fromSedeWS:sedeWS];
if (statoSede == 2 && sede.tour)
sede.eliminata = YES;
}
}
[BOTManagedObjectContext save];
for (Contatto *contatto in contattiDel)
{
[BOTManagedObjectContext deleteObject:contatto];
}
[BOTManagedObjectContext save];
for (Sede *sede in sediDel)
{
[BOTManagedObjectContext deleteObject:sede];
}
[BOTManagedObjectContext save];
}
谢谢。
答案 0 :(得分:5)
执行许多查找的最快方法是将NSArray
转换为NSDictionary
。此初始转换将采用线性时间,这与当前循环所用的时间相同。 然而,未来的查找只会花费一些时间!
NSArray *sedeArray = [Sede sedeArray];
NSMutableDictionary *itemsByItemID = [NSMutableDictionary dictionary];
for (Sede *sede in sedeArray) {
itemsByItemID[@(sede.idSede)] = sede;
}
self.sedesBySedeID = itemsByItemID;
此方法只需要一段时间来查找对象。
- (Sede *)sedeForSedeID:(int)sedeID {
return self.sedesBySedeID[@(sedeID)];
}
答案 1 :(得分:4)
使用排序数组的优点是可以对其进行二进制搜索,而不是对其进行线性搜索。 Wikipedia对算法有很好的描述。
要做到这一点,你从中间开始,然后,如果你还没有找到该值,检查你是否过高或过低,并向相反的方向跳一半。最终,你要么找到价值,要么找到"中途"将是0步,你知道它不存在。
这足以让你入门。
NSUInteger findInSortedArray(NSArray *arr, id obj) {
NSUInteger low = 0;
NSUInteger high = arr.count;
while (low + 1 < high) {
NSUInteger mid = (low + high) / 2;
if ([arr[mid] isEqual:obj]) return mid;
// ..
}
return -1;
}
(您还可以在互联网上找到可以让您更轻松的分类收藏库。)
如果所有你正在检查会员资格,那么,有一个更简单的解决方案:使用NSSet
代替NSArray
,或NSDictionary
将id
映射到其对象。