简单地初始化String和使用retain有什么区别?

时间:2011-09-05 07:42:51

标签: ios objective-c cocoa-touch memory-management

我想知道以下两行之间的区别

 name1 = [[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,1)] retain];

 name1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,1)];

如果我最后使用retain,

会对name1产生什么影响

我遇到问题,并且无法在NSTimer调用的方法中使用name1,当我使用retain时,它们对我来说很好。

如果我在viewDidLoad中调用数据库中的值,并在每秒后使用NSTimer调用的方法,那么它将给出bad-exec,但是当我使用retain时它会正常工作,

我想知道原因

3 个答案:

答案 0 :(得分:4)

这是差异

- (void)func1 {
    name1 = [[NSString stringWithUTF8String:...] retain];
    name2 = [NSString stringWithUTF8String:...];
}

- (void)func2 {
    NSLog(@"%@", name1);    //OK, name1 is still there
    NSLog(@"%@", name2);    //Would be crashed because name2 could be released anytime after func1 is finished.
}

答案 1 :(得分:2)

我在另一个问题上写了这个答案,但它解释了你在问什么:

目标c中的对象具有保留计数。如果当对象超出范围时(当您停止使用它时)此保留计数大于0,则它会泄漏。

以下事项会增加保留计数

[[alloc] init]
new
copy
[retain]
adding an object to an array
adding an object as a child (e.g. views)
There are likely more, but you don't appear to use any others in your code

以下减少保留计数

[release]
removing an object from an array
if you dealloc an array, all of its objects are released

您应该检查代码并确保数组的每个保留或添加都与相应的版本匹配。 (您可以在dealloc方法中释放成员变量。)

另一位用户提出了一个有效的观点,即我的答案不是

  

将对象添加到数组后,它将获得所有权,并在完成对象时释放该对象。您需要做的就是确保根据内存管理规则发布您拥有的任何内容

还有自动释放对象,看看这个例子;

-(init){
    ...
    stagePickerArray = [[NSMutableArray alloc] init];
    for (int i = 0; i < 3; i++)
    {
        //this string is autoreleased, you don't have call release on it.
        //methods with the format [CLASS CLASSwithsomething] tend to be autorelease
        NSString *s = [NSString stringWithFormat:@"%d", i);
        [stagePickerArray addObject:s];
    }
    ...
 }

您的问题是,当您稍后使用字符串时,它的保留计数为零并且已被释放。通过在上面调用retain,你会说“我想稍后再使用它”。不要忘记将每个保留与释放匹配,否则你的对象将“泄漏”

答案 2 :(得分:1)

我敢打赌,如果您的name1是属性,则代码不会崩溃 - (nonatomic, retain)(copy),具体取决于您的需求。

第二个条件是在你的其他函数尝试使用它时将name1初始化为有意义的。

修改
对于属性,在这种情况下,您必须使用合成的setter:self.name1 = @"your string"; 通常,您不必手动保留/释放使用stringWith...方法创建的字符串,因为您使用显式alloc在内存中没有创建任何内容。另请注意,代码:
NSString *str = [NSString stringWithUTF8String:@"your string"]; 当函数超出范围时,str(如果不用于设置属性)将停止可用(iOS eventloop将自动释放它)。