内存高效的集合类

时间:2010-05-28 16:46:29

标签: iphone objective-c

我正在我的iphone应用程序中构建一个字典数组(称为键)来保存tableview的节名和行数。

代码如下所示:

[self.results removeAllObjects];
[self.keys removeAllObjects];

NSUInteger i,j = 0;
NSString *key = [NSString string];
NSString *prevKey = [NSString string];

if ([self.allResults count] > 0)
{
    prevKey = [NSString stringWithString:[[[self.allResults objectAtIndex:0] valueForKey:@"name"] substringToIndex:1]];

    for (NSDictionary *theDict in self.allResults)
    {
        key = [NSString stringWithString:[[theDict valueForKey:@"name"] substringToIndex:1]];

        if (![key isEqualToString:prevKey])
        {
            NSDictionary *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                           [NSNumber numberWithInt:i],@"count",
                                           prevKey,@"section",
                                           [NSNumber numberWithInt:j],
                                           @"total",nil];

            [self.keys addObject:newDictionary];
            prevKey = [NSString stringWithString:key];
            i = 1;
        }
        else
        {
            i++;
        }
        j++;

    }

    NSDictionary *newDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:i],@"count",
                                   prevKey,@"section",
                                   [NSNumber numberWithInt:j],
                                   @"total",nil];

    [self.keys addObject:newDictionary];

}

[self.tableview reloadData];

代码第一次运行正常,但有时我必须重建整个表,所以我重做这个代码,它在模拟器上运行得很好,但是在我的设备上程序在我执行reloadData行时发生炸弹:

malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Program received signal:  “EXC_BAD_ACCESS”.

如果删除reloadData行,代码将在设备上运行。

我想知道这是否与我构建密钥数组的方式有关(即使用自动释放的字符串和字典)。

3 个答案:

答案 0 :(得分:15)

错误消息为您提供了分配失败的明确原因:

malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
malloc: *** mmap(size=3772944384) failed (error code=12)
*** error: can't allocate region

具体来说,大小为3,772,944,384;差不多4GB。即你要求malloc()分配一些东西,导致malloc认为它需要内存映射(mmap)近4GB的地址空间!

现在,如果您的输入字符串确实很大,那么您的代码将像davydotcom所说的那样膨胀自动释放池,但是他们必须非常真正巨大才能导致这种情况发生。如果它是那么大,那么你最终会在桌子上成千上万行或几十万行吗?如果是这样,请不要这样做 - 用户太难以使用。

如错误所示,请在malloc_error上设置断点并发布回溯。

请注意:

NSString *key = [NSString string];
NSString *prevKey = [NSString string];

废话。

好的 - 您的代码第二眼就会表明对Objective-C guideCocoa memory management指南的审核会很有用。

在前四行代码中,您都泄漏了前一行并过度保留了新的self.keysself. self.results(假设两者都是retain属性,因为它们应该是这样的。

还要尝试使用Build&分析你的代码。

答案 1 :(得分:0)

如果可能的话,我强烈建议不要使用自动释放的字符串和对象,因为它们也会降低性能。代码集中的所有内容看起来都是正确的,除了顶部的奇数语句。

前两行从数组中删除所有对象,然后指定指向新self.keys和self.results的指针

只分配self.keys和self.results一次,重新加载数据时只需调用removeAllObjects。

答案 2 :(得分:0)

一个名为keys的字典数组... [self.keys addObject:newDictionary] ..需要..谎言..下来。