为啥需要保留 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 变量?的主要内容,如果未能解决你的问题,请参考以下文章