iPhone:快速枚举,速度不够快?
我正在尝试通过其中包含大约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秒或更长时间,而且似乎让用户等待太久了!
想法?
您使用快速枚举设置循环,然后您忽略它。
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:...];
}
的这些变化都将加快你的代码,并显著减少内存使用情况,并可能会消除一切是造成你所遇到的奇怪的错误。
三件事:
- 你通过一个数组,没有一套循环。如果你不关心订单,请循环播放。
- 您没有使用“快速枚举”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]];
}
谢谢。我需要先排序我的设置,这就是为什么它是一个数组。我修复了循环以实际使用快速枚举以及NSMutableString,它确实加快了速度,允许我遍历所有6500值。 我正在使用我自己的Location类核心数据,它创建了双倍的NSNumbers。不知道如何改变这一点。 ( – 2010-08-15 23:56:59
让你的函数返回一个double而不是一个NSNumber *?这不是特别困难 – 2010-08-16 22:07:45
不知道是什么导致你的程序错误,但有两件事情可以改善:
- 一旦你使用快速列举列举你的容器没有必要按索引获得项目
-
使用NSMutableString累加值
NSMutableString *cord = [NSMutableString string]; for (CLLocation* loc in sortedArray) { [cord [email protected]"%f,%f ",[loc.longitude doubleValue],[loc.latitude doubleValue]]; }
它看起来像你的应用程序被终止在这个迭代发生时占用主线程。
您应该使用NSOperation
来完成任务并异步执行它。您需要回调到主线程才能完成,但尝试在主线程上执行此操作是一种破碎的用户体验 - 即使它只需要3秒钟。
我只是碰到了一个有趣的(也可能鲜为人知的)实际上是约迭代的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.
事实上,我发现,迭代使用基于块的方法比快速列举稍微快一点,当你正在使用NSSet。它比在集合的allObjects数组上使用快速枚举还要快一些。
谢谢你,我是新手,仍然在学习,我像你说的那样做了修改,并且显着加快了我的代码,允许我遍历所有6500个项目。 – 2010-08-15 23:54:16