为什么需要保留NSString变量?

KVr*_*ron 2 iphone objective-c autorelease nsstring retain

我的.h文件中有以下代码:

@interface Utils : NSObject {
    NSString *dPath;
}    
@property(nonatomic, retain) NSString *dPath;
Run Code Online (Sandbox Code Playgroud)

在我的.m文件中:

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
[dPath retain]; 
Run Code Online (Sandbox Code Playgroud)

如果dPath已经定义为(非原子,保留),为什么还要保留 dPath?如果我不添加[dPath retain]; 我得到一些奇怪的,随机的错误,并且在其他函数中使用此变量时应用程序崩溃.我想这是因为某些自动释放,但我没有.

那么,什么是(非原子的,保留)做什么呢?是否真的有必要[dPath保留]; 或者我只是隐藏其他东西?

Bol*_*ock 7

因为代码没有调用dPath属性的setter方法,所以它只是dPath直接设置实例变量:

dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
[dPath retain]; 
Run Code Online (Sandbox Code Playgroud)

所以必须手动保留.

retain如果像这样使用属性setter(注意self.),你将能够(事实上你需要)省略调用:

self.dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
Run Code Online (Sandbox Code Playgroud)

或者像这样(注意setDPath:):

[self setDPath:[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName]];
Run Code Online (Sandbox Code Playgroud)

二传手保留NSString给你,所以你不必自己动手.


为了避免混淆,要遵循一个很好的小练习,就是在你的ivar名称上加上一个下划线,表示它是一个ivar:

    NSString *dPath_;
Run Code Online (Sandbox Code Playgroud)

然后像这样合成你的属性,将它与你的不同命名的ivar相关联:

// self.dPath is the property, dPath_ is the ivar
@synthesize dPath = dPath_;
Run Code Online (Sandbox Code Playgroud)

然后修改您的dealloc方法,以及直接引用实例var的任何其他代码,以使用附加的名称:

- (void)dealloc {
    [dPath_ release];

    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

  • 在NSString属性上使用copy而不是retain也是一种好习惯.原因是NSMutableString可以在没有编译器警告的情况下轻松分配给NSString,然后在将来进行更改. (3认同)