2010-08-15 105 views
0

我正在尝试通过其中包含大约6500个项目的NSSet进行循环。我正在使用:iPhone:快速枚举,速度不够快?

for (id Location in sortedArray) { 
      loc = [sortedArray objectAtIndex:i]; 
      cord = [cord stringByAppendingString:[NSString stringWithFormat:@"%f,%f ",[loc.longitude doubleValue],[loc.latitude doubleValue]]]; 
      i++; 
     } 

这工作正常,但它似乎不够快。它得到约项目5700,我得到以下错误:

Program received signal: “0”. 
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib") 

有没有办法循环通过数据比这更快?它需要大约20秒或更长时间,而且似乎让用户等待太久了!

想法?

回答

7

您使用快速枚举设置循环,然后您忽略它。

for (id Location in sortedArray) { 
    loc = [sortedArray objectAtIndex:i]; 

第一行设置一个名为Location环路本地变量,它在每次迭代中,点阵列中的一个项目。但是您忽略该变量并使用第二个变量loc,并且第二次从该数组中获取该值。你应该把它改写为:

for (id loc in sortedArray) { 
    cord = [cord stringByAppendingString:...] 
} 

虽然我们在这,你正在构建的cord字符串的方法是坚果。您通过循环在每次迭代中创建一个新字符串。在每次迭代中使用NSMutableString并调用appendFormat:会更聪明。然后你就不会在自动释放池中填充数千个未使用的NSString对象。因此,像这样:

NSMutableString *cord = [NSMutableString string]; 
for (id loc in sortedArray) { 
    [cord appendFormat:...]; 
} 

的这些变化都将加快你的代码,并显著减少内存使用情况,并可能会消除一切是造成你所遇到的奇怪的错误。

+0

谢谢你,我是新手,仍然在学习,我像你说的那样做了修改,并且显着加快了我的代码,允许我遍历所有6500个项目。 – 2010-08-15 23:54:16

6

三件事:

  • 你通过一个数组,没有一套循环。如果你不关心订单,请循环播放。
  • 您没有使用“快速枚举”API。
  • + [NSString stringWithFormat:]返回一个自动释放对象。 - [NSString stringByAppendingString:]返回另一个自动释放对象。你使用了很多内存。
  • - [NSString stringByAppendingString:]自己创建一个副本,然后附加新的字符串。每次制作一个字符串时,复制量都会增加;你的算法是O(n )。 6500 相当大。

此外,它看起来像你使用自己的位置类。改变它返回双打而不是(我假设)NSNumber * s。绝对不会返回NSStrings;从字符串转换为双是slooooooow。或者,返回一个CLLocationCoordinate2D(一个两个双精度结构)以避免额外的方法调用。

让我无耻地重写代码:

NSMutableString * cord = [NSMutableString stringWithCapacity:cord.count*20]; 
for (Location * loc in sortedArray) { 
    [cord appendFormat:@"%f,%f ",[loc.longitude doubleValue],[loc.latitude doubleValue]]; 
} 
+0

谢谢。我需要先排序我的设置,这就是为什么它是一个数组。我修复了循环以实际使用快速枚举以及NSMutableString,它确实加快了速度,允许我遍历所有6500值。 我正在使用我自己的Location类核心数据,它创建了双倍的NSNumbers。不知道如何改变这一点。 ( – 2010-08-15 23:56:59

+0

让你的函数返回一个double而不是一个NSNumber *?这不是特别困难 – 2010-08-16 22:07:45

1

不知道是什么导致你的程序错误,但有两件事情可以改善:

  1. 一旦你使用快速列举列举你的容器没有必要按索引获得项目
  2. 使用NSMutableString累加值

    NSMutableString *cord = [NSMutableString string]; 
    for (CLLocation* loc in sortedArray) { 
        [cord [email protected]"%f,%f ",[loc.longitude doubleValue],[loc.latitude doubleValue]];    
    } 
    
0

它看起来像你的应用程序被终止在这个迭代发生时占用主线程。

您应该使用NSOperation来完成任务并异步执行它。您需要回调到主线程才能完成,但尝试在主线程上执行此操作是一种破碎的用户体验 - 即使它只需要3秒钟。

0

我只是碰到了一个有趣的(也可能鲜为人知的)实际上是约迭代的NSSet中:

The per-iteration overhead of the fast-enumeration loop varies by the collection type — basically, whether the collection forces the code to go back for more elements after each iteration. For an array, it does not; for a set, IIRC it does. The possibility makes it hard for the compiler to reason about memory across iterations of the loop (which would otherwise be a significant advantage of fast-enumeration), and in either case there's extra overhead because of the mandatory modification checks.

...

As a rule of thumb, iterating with a block is almost always best if you're not iterating over an array.

Source

事实上,我发现,迭代使用基于块的方法比快速列举稍微快一点,当你正在使用NSSet。它比在集合的allObjects数组上使用快速枚举还要快一些。