1

我很好奇我用工厂方法分配的内存。这个想法是,我将读入一个文件,然后通过向我的工厂方法发送一个未解析的 CSV 行来实例化对象,如下所示:

-(id)initWithCSV:(NSString *)csv
{
    if(self = [super init])
    {
        NSArray *values = [csv componentsSeparatedByString:@","];
        self.city = [values[0] stringByTrimmingCharactersInSet:
            [NSCharacterSet whitespaceCharacterSet]];
        self.country = [values[1] stringByTrimmingCharactersInSet:
            [NSCharacterSet whitespaceCharacterSet]];
        self.latitude = [values[2] doubleValue];
        self.longitude = [values[3] doubleValue];
    }
    return self;
}

我的第一个问题是,这在内存管理方面如何?我不完全清楚 ARC 是如何工作的。values一旦我return self;退出该方法,我的数组就会被销毁,对吗?

第二个问题......有没有更有效的方法来完成我在这里尝试做的事情?

4

3 回答 3

2

TL/DR:如果您使用 ARC,那么您的方法非常节省内存。

这实际上展示了 ARC 的一个有趣特性,这与componentsSeparatedByString:自动释放的输出有关。

假设你有这个功能:

while ((line = [self readLine])) {
    [self.lines addObject:[[MyObj alloc] initWithCSV:line];
}

如果没有 ARC,这个看似高效的函数可能会消耗大量内存,因为 in 中的对象values会一直保留到自动释放池耗尽为止。(实际上与line上面相同。)优化此的一种传统方法是执行以下操作:

while ((line = [self readLine])) {
    @autoreleasepool {
        [self.lines addObject:[[MyObj alloc] initWithCSV:line];
    }
}

这样,当您到达池的末尾时,自动释放的values就会被释放。当然,您会因为耗尽池而受到性能影响。

一个幼稚的 ARC 实现不能解决这个问题。它会在作用域的末尾看到componentsSeparatedByString:, call[values retain]和 call的 +0 输出。[values release]

ARC 实际上所做的是调用一个函数objc_retainAutoreleasedReturnValue(values),而不是保留values,而是将其从自动释放池中删除。这样,当它[values release]在作用域结束时调用时,数组就会被释放。同样,它会line在我的循环的每次迭代中巧妙地释放。

这提供了出色的内存和 CPU 效率。

于 2013-10-10T23:40:46.420 回答
2

关于你的第一个问题:

在这种情况下,ARC 实际上并没有什么不同。由于该commentsSeparatedByString:方法已经返回了一个自动释放的对象,并且您没有增加它的保留计数(或者在 ARC 术语中,创建任何强引用),所以当方法返回时它会被自动清除。

至于效率,您可能可以通过使用 NSScanner 扫描每个逗号来节省一些内存,而不是创建一个包含一堆字符串的数组。但是由于这只是一些相对较短的字符串,因此实际上并不重要。

于 2013-10-10T23:25:40.063 回答
0

我认为 NSArray 被释放是init因为自动释放池的范围受到限制。但是self.latitude例如,这些值会被复制。

于 2013-10-10T23:25:06.910 回答