Init方法,内存管理

时间:2013-10-10 23:21:52

标签: objective-c memory-management initialization

我很好奇我用工厂方法分配的内存。我的想法是,我将在一个文件中读取,并且我将通过向我的工厂方法发送单个未解析的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;后立即销毁并退出方法,对吗?

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

3 个答案:

答案 0 :(得分:2)

关于你的第一个问题:

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

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

答案 1 :(得分:2)

TL / DR:如果你使用ARC,你的方法非常有效。

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

说你有这个功能:

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

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

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

这样,当您点击池的末尾时,将释放自动释放的values。你当然会因为耗尽游泳池而受到性能影响。

天真的ARC实施无法解决此问题。它会看到componentsSeparatedByString:的+0输出,调用[values retain]并在范围结束时调用[values release]

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

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

答案 2 :(得分:0)

我认为NSArray已发布,因为init的范围受限于自动释放池。但是这些值会复制到self.latitude中。