我想了解如何设置属性(访问器)的参数。
我从 Kal 日历的示例中获取了以下代码。
// Holiday.h
@interface Holiday : NSObject
{
NSDate *date;
NSString *name;
NSString *country;
}
@property (nonatomic, retain, readonly) NSDate *date;
@property (nonatomic, retain, readonly) NSString *name;
@property (nonatomic, retain, readonly) NSString *country;
- (id)initWithName:(NSString *)name country:(NSString *)country date:(NSDate *)date;
@end
// Holiday.m
#import "Holiday.h"
@implementation Holiday
@synthesize date, name, country;
- (id)initWithName:(NSString *)aName country:(NSString *)aCountry date:(NSDate *)aDate
{
if ((self = [super init])) {
name = [aName copy];
country = [aCountry copy];
date = [aDate retain];
}
return self;
}
- (void)dealloc
{
[date release];
[name release];
[country release];
[super dealloc];
}
@end
1)属性设置为
retain
,但由于不能使用 setter retain
在这里没有任何意义。2)另外,在
initWithName
方法使用 copy
设置值.为什么不直接用 copy
定义属性并使用访问器方法?@property (nonatomic, copy) NSString *name;
// ...
self.name = aName;
3) 我需要
readonly
吗?这里?我不知道为什么在这里使用它们。如果我使用 copy
连同 setter readonly
禁止我设置值,因为没有 setter 。4) 在
initWithName
方法有时 copy
有时 retain
用来。我建议始终使用 copy
在这里,因为以后不应修改该值。5) 我记得是可以到
copy
/retain
在 initWithName
和 release
在 dealloc
方法。那么您建议如何使用
retain
, copy
和 readonly
在这个例子中?
最佳答案
预计到达时间: @DougW 正确地指出属性的所有权类型( assign
/retain
/copy
)不会影响 getter。它仍然会影响二传手。对于 readonly
类型,如果您要覆盖 readonly
,这很重要类扩展中声明的一部分,因此您可以在您的实现中使用 setter。类扩展属性覆盖只允许更改 readonly
属性的状态,所以它的其余部分 - 这意味着原子性和所有权类型 - 必须在标题中适本地声明。即使您现在没有覆盖该属性,将来也可能会覆盖该属性,因此您最好通过使用正确的选项开始记录您希望如何为自己管理内存。
自动引用计数 (ARC) 通过在经典引用计数规则之上覆盖其自己的内存管理规则来更改运行时实现细节,但用于配置属性的规则和建议保持不变。
为什么使用 retain
与 readonly
? 如果您将属性标记为 retain
, 合成访问器做这样的事情:
/* getter for retain property */
- (NSString *)name {
return [[name retain] autorelease];
}
现在,如果您发送的对象
-name
要在您仍在使用它时更改名称,调用代码仍将具有对字符串的有效引用。如果您将其声明为 assign
,不过,它会是这样的:/* getter for assign property */
- (NSString *)name {
return name;
}
现在,只要对象更改了名称,就必须将其释放以避免泄漏,这将使调用代码的引用无效。
retain
/copy
/assign
确实在说明内存管理策略:retain
/copy
说,“我保证我持有对我在此处提供的值的原始/副本的引用”,而 assign
说,“我只是拥有值(value),并声称没有对此的所有权。”当值不需要内存管理时,比如一个普通的
int
,然后 assign
说得通。如果您有意不保留对象(例如委托(delegate)),则 assign
说得通。但是,在大多数其他情况下,您需要 retain
或 copy
.此外,实现文件只能覆盖
readwrite
/readonly
属性声明的一部分,而不是内存管理部分。正如声明的那样,.m
文件可以有:@interface Holiday (/*class extension*/)
@property(nonatomic, retain, readwrite) NSDate *date;
/* override other properties to make them readwrite... */
@end
被覆盖的属性声明的非公共(public) setter 将与公共(public)访问器一起合成。
为什么不在
-init
期间使用 setter/accessors ? 因为 setter/accessors 经常执行 KVO 通知,当您的对象未完全初始化时,即在 -init
期间,您希望避免这种通知。 (当它在完全初始化的过程中半初始化时)和 -dealloc
(当它在完全未初始化的过程中半初始化时)。为什么使用
copy
与 readonly
? 正如回答你的第一个问题:因为如果copy
与 retain
与 assign
影响 setter 和 getter。一个副本 getter 看起来像这样:/* getter for copy property */
- (NSString *)name {
return [[name copy] autorelease];
}
为什么有时
copy
有时 retain
? copy
通常与值对象(表示值的被动对象)一起使用; retain
通常与其他对象一起使用。有时,效率问题会发挥作用(很可能过早......),您可能会选择使用 retain
您通常会在哪里使用 copy
.您将如何使用
copy
/retain
连同 readonly
这里? 和他们做的差不多。我会覆盖类扩展中的声明,以便我可以使用 setter 来更改 -init
之外的属性值。和 -dealloc
,我只会使用直接实例变量访问。我也会nil
在 -dealloc
中释放 ivars 后将其取出,例如,[name release], name = nil;
这有助于避免向已发布的对象发送消息或以其他方式引用已发布的对象。
关于iphone - 初始化程序、属性、访问器和复制/保留/只读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4044150/