为啥需要保留 NSString 变量?

Posted

技术标签:

【中文标题】为啥需要保留 NSString 变量?【英文标题】:Why NSString variable needs to be retained?为什么需要保留 NSString 变量? 【发布时间】:2011-02-05 06:34:09 【问题描述】:

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

@interface Utils : NSObject 
    NSString *dPath;
    
@property(nonatomic, retain) NSString *dPath;

在我的 .m 文件中:

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

如果它已经定义为(非原子,retain),为什么我必须retain dPath? 如果我不添加 [dPath 保留];在其他函数中使用此变量时,我得到一些奇怪的随机错误并且应用程序崩溃。我猜这是因为这里有一些 autorelease 但我没有。

那么,(nonatomic, retain) 到底在做什么呢? [dPath 保留] 真的有必要吗?还是我只是在隐藏其他东西?

【问题讨论】:

如果您在 Utils 中设置 dPath,请确保您使用的是 self.dPath,而不仅仅是 dPath 【参考方案1】:

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

dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
[dPath retain]; 

所以必须手动保留。

如果像这样使用属性设置器,您将能够(实际上您需要)省略retain 调用(注意self.):

self.dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];

或像这样(注意setDPath:):

[self setDPath:[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName]];

setter 会为您保留NSString,因此您不必自己动手。


为了避免混淆,一个很好的小做法是在您的 ivar 名称后面加上一个下划线以表明它是一个 ivar:

    NSString *dPath_;

然后像这样合成您的属性,将其与您的不同名称的 ivar 相关联:

// self.dPath is the property, dPath_ is the ivar
@synthesize dPath = dPath_;

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

- (void)dealloc 
    [dPath_ release];

    [super dealloc];

【讨论】:

我刚刚按照您的建议更改了代码,并且......它正在工作。到目前为止没有崩溃。我想我需要回到 Objective-C 的基础知识 :( 谢谢!! @KVron:不客气!遇到困难时,您可以随时再次参考documentation。请记住通过单击答案旁边的空心复选标记将答案标记为已接受。 在 NSString 属性上使用复制而不是保留也是一个好习惯。原因是 NSMutableString 可以很容易地分配给 NSString 而不会出现编译器警告,然后在将来更改。【参考方案2】:

尝试设置和获取它

self.dPath

【讨论】:

【参考方案3】:

如果你想调用属性setter方法,它会调用retain,那么你想写:

self.dPath = ...

通过以下方式将内容塞入变量中:

dPath = ...

完全忽略此实例变量的属性。这就是您最终需要手动保留的原因。

【讨论】:

以上是关于为啥需要保留 NSString 变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何增加 NSString 类型变量的保留计数? [复制]

UITableView 在保留已经获取的行的同时插入更多行

重写description方法

为啥 Xcode 认为我的变量在应该返回 NSString 时却返回了 NSURL?

NSString 到 NSUInteger

为啥不声明实例变量?