迭代for循环时变慢

Posted

技术标签:

【中文标题】迭代for循环时变慢【英文标题】:Getting slow when iterate for loop 【发布时间】:2015-11-24 07:07:12 【问题描述】:

for ( NSDictionary *detailsDict in rsltArray) NSString *OfficeId =[detailsDict objectForKey:@"ObjectId"]; NSString *catID =[detailsDict objectForKey:@"catID"]; NSString *ObjType =[detailsDict objectForKey:@"ObjectType"];

        NSString *getImage = [NSString stringWithFormat:@"select catMarkericon from TBL_Category where catID='%@'",catID];
        NSMutableArray * imageArray = [self.database getDataListBySQLQueryStatement:getImage];
        NSString *officeLogo  = [[imageArray objectAtIndex:0] objectForKey:@"catMarkericon"];

        NSArray *parts = [officeLogo componentsSeparatedByString:@"/"];
        NSString *filename = [parts lastObject];


        NSString *OfficeName;
        NSString *OfficeAddress;
        if([[UserDefaults getLanguageSelection]isEqualToString:@"en"])
        
            OfficeName  =[detailsDict objectForKey:@"ObjectNameEnglish"];
            OfficeAddress  =[detailsDict objectForKey:@"ObjectAddressEnglish"];
        
        else
        
            OfficeName  =[detailsDict objectForKey:@"ObjectNameArabic"];
            OfficeAddress  =[detailsDict objectForKey:@"ObjectAddressArabic"];
        

        double Off_lat      =[[detailsDict objectForKey:@"Latitude"] doubleValue];
        double Off_long     =[[detailsDict objectForKey:@"Longitude"] doubleValue];

        tempLocation = [[CLLocation alloc] initWithLatitude:Off_lat longitude:Off_long];
        CLLocationDistance meters = [tempLocation distanceFromLocation:CurrentLoc]/1000;

        if(meters<=Dist)
        
            [arrListdata addObject:detailsDict];
            if ([catID isEqualToString:selectID]) 
                tempCoordinate = [ARGeoMarkerco coordinateWithLocation:tempLocation locationTitle:OfficeName withid:OfficeId withaddress:OfficeAddress withimage:filename withcatId:catID withObjType:ObjType selectValue:YES newmarker:NO];
                [locationArray addObject:tempCoordinate];
            
            else
                tempCoordinate = [ARGeoMarkerco coordinateWithLocation:tempLocation locationTitle:OfficeName withid:OfficeId withaddress:OfficeAddress withimage:filename withcatId:catID withObjType:ObjType selectValue:NO newmarker:NO];
                [locationArray addObject:tempCoordinate];
            

    


我正在使用这样的 for 循环,我必须迭代超过 1500 个数据,并且它会在 4 到 7 秒内卡住我的应用程序是任何解决此问题的方法

【问题讨论】:

您需要显示更多代码。你对每本字典做什么。循环本身根本不会花费太多时间。 根据您给我们的信息:编写高效的代码,使用高效的数据结构。 NSEnumerator *e = [array objectEnumerator];标识对象; while (object = [e nextObject]) // 对对象做一些事情 听起来您想为此使用后台线程,以避免阻塞主(UI)线程。 1500 不应该太大而不能通过蛮力完成。字典里有什么? 【参考方案1】:

我必须用 Objective C/pseudocode 混合来写这个,只是为了尽快给你答案。

将 1500 个成员数组拆分为 2 个。

NSRange theRange;
NSRange theSecondRange;
theRange.location = 0;
theRange.length = 749;
theSecondRange.location = 750;
theSecondRange.length = 750;    
NSArray *array1 = [rsltArray subarrayWithRange:theRange];
NSArray *array2 = [rsltArray subarrayWithRange:theSecondRange];

然后,在后台创建 2 个调度队列。使用您拥有的代码将第一个数组从第一个队列中取出。对第二个做同样的事情。线程完成后,使用 NSArray arrayByAddingObjectsFromArray 将它们放在一起。

如果仍然太慢,请将数组进一步拆分为 4 或 8 个,并将它们线程化到单独的队列中。诀窍是您必须等到线程返回后再添加它们,否则您的应用程序将崩溃,因为不会有一个数组可以添加回一个主数组。 更新请参阅 Apple 上的此链接,了解 Grand Central Dispatch 中的调度组,以处理我提到的子阵列何时返回 https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/doc/uid/TP40008079-CH2-SW19

【讨论】:

如果任务可以同时完成那么使用dispatch_apply可能会简单很多 但是我的数组不是静态数组,它与api数据相关,将来会是5000或以上。 然后像文档theRange.length = [wholeArray count] / 2; 那样使用对您的数组长度有意义的分母来拆分数组 我已经应用了你的逻辑,目前情况没有改变 @iosDev 数组从线程返回后如何返回是一个问题。基本上,您的线程会同时执行,但它们完成时不一定按照您想要的顺序。例如,线程 1 可以在线程 5 之后完成。如何处理这种情况是困难的部分,取决于最终数据结构的设计。您可能想问一个关于 SO 的更具体的问题,关于如何设计一个数据结构或类,一旦它们完成就可以完成线程的连接。它应该比主线程上的串行执行快得多。

以上是关于迭代for循环时变慢的主要内容,如果未能解决你的问题,请参考以下文章

web性能优化--算法优化

为啥在 for 循环之后比 for 循环之前慢得多?

for循环增强for循环和迭代器的区别

如何强制结束 for 循环的迭代(不停止 for 循环)?

python中for循环的底层实现机制 迭代

哪个更好,单 for 循环或双 for 循环迭代二维数组? C++