2011-09-05 65 views
2

我想知道下面两行简单地使用NSString和保留来初始化有什么区别?

之间的差异
name1 = [[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,1)] retain]; 

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

会有什么在影响NAME1如果我不使用保留在最后,

我曾经面对的问题,并不能使用NAME1一个由NSTimer调用的方法,当我使用retain时,它对我来说工作得很好。

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

我想知道原因

+3

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html – zneak

+0

@Zneak,我知道保留会增加计数+1,但是什么原因这样的行为? –

+2

请[请花点时间阅读介绍](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/ 20000994-SW1)。你的程序崩溃了,因为你在一个释放的对象上使用了一个方法,并且你的对象被释放了,因为在你的定时器代码运行时,没有人取得它的所有权。 – zneak

回答

4

这是我敢打赌,你的代码不会崩溃,如果你name1是一个性质的差异

- (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. 
} 
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方法中释放成员变量)。

另一位用户提出我的回答没有

一旦你添加一个对象到一个数组一个有效的点,它取得所有权,当它与它做会释放对象。你所要做的就是确保你根据内存管理规则释放你自己拥有的任何内容。

还有一些autorelease对象,看看这个例子;

-(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,你就会说'我想稍后使用它'。不要忘了匹配每一个保留与释放,或者你的对象将“泄漏”

+0

但是当你在name1中赋值并且可以在任何主体中使用时,除了在被时间调用的方法中,我没有解决任何调用方法(从db获取值并保存到name1的获取方法)中的在被定时器调用的方法内,否则使用retain,但不能理解原因,你能否解释它 –

1

- 根据您的需求选择(nonatomic, retain)(copy)

第二个条件是让name1初始化为在您的其他函数试图用它做某事时有意义。

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

相关问题