<code>
//header file has appropriate declarations but not included here:
#import "AddressCard.h"
@implementation AddressCard;
-(NSString *) name
{
return name;
}
//Recommended code:
-(void) setName: (NSString *) theName
{
[name release]
name = [[NSString alloc] initWthString: theName];
}
//Incorrect code according to Kochan:
-(void) setName: (NSString *) theName
{
[name release]
name = [NSString stringWthString: theName];
}
//rest of class implementation code snipped
@end
<code>
所以我在堆栈溢出上看到了这个代码,这不是我的代码,我不是想接受它,或者我只是对目标C中的这段代码有一个快速的问题。在(void) setName: (NSString *) theName
方法中为什么我们必须[name release]
然后name = [[NSString alloc] initWithString: theName]
。
为什么我们不能简单地说name = theName
。这不会只是将theName
方法中作为参数传递的setName
变量复制到原始name
变量中吗?
很抱歉,如果这是一个糟糕的问题,但我是目标c的新手,对来自java背景的内存管理有点困惑。
答案 0 :(得分:2)
正确的现代风格是在项目中使用ARC(自动引用计数),这是新项目的默认设置(已经有几年了)。然后,您不需要也不允许发送release
消息。
initWithString:
与stringWithString:
的选择在ARC下没有任何区别,您也可以这样写出来:
- (void)setName:(NSString *)theName {
name = [theName copy];
}
使用copy
(或initWithString:
或stringWithString:
),即使来电者传入name
,您也可以确保NSMutableString
不会改变然后改变其内容。
但是如果你只想做你在问题中所做的事情,你可能甚至不需要写一个二传手。您需要做的就是将其放在.h
文件中:
@interface AddressCard
@property (nonatomic, strong) NSString *name;
// other declarations...
@end
如果省略它们,编译器将自动生成一个实例变量(名为_name
),一个setter和一个getter。但是,使用strong
表示编译器生成的setter不会复制字符串;它只会保持对调用者给出的字符串的引用。
如果您想使用上面描述的copy
,请改为声明属性:
@property (nonatomic, copy) NSString *name;
然后编译器将生成一个使用copy
。