iphone - 初始化程序、属性、访问器和复制/保留/只读

标签 iphone objective-c properties initialization accessor

我想了解如何设置属性(访问器)的参数。

我从 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/retaininitWithNamereleasedealloc方法。

那么您建议如何使用 retain , copyreadonly在这个例子中?

最佳答案

预计到达时间: @DougW 正确地指出属性的所有权类型( assign/retain/copy )不会影响 getter。它仍然会影响二传手。对于 readonly类型,如果您要覆盖 readonly,这很重要类扩展中声明的一部分,因此您可以在您的实现中使用 setter。类扩展属性覆盖只允许更改 readonly属性的状态,所以它的其余部分 - 这意味着原子性和所有权类型 - 必须在标题中适本地声明。即使您现在没有覆盖该属性,将来也可能会覆盖该属性,因此您最好通过使用正确的选项开始记录您希望如何为自己管理内存。

自动引用计数 (ARC) 通过在经典引用计数规则之上覆盖其自己的内存管理规则来更改运行时实现细节,但用于配置属性的规则和建议保持不变。

为什么使用 retainreadonly ? 如果您将属性标记为 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说得通。但是,在大多数其他情况下,您需要 retaincopy .

此外,实现文件只能覆盖 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 (当它在完全未初始化的过程中半初始化时)。

为什么使用 copyreadonly ? 正如回答你的第一个问题:因为如果copyretainassign影响 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/

相关文章:

iphone - 如何在iPhone应用程序中定期补充游戏货币。

iphone - KalViewController View 为黑色

iphone - UIPageControl 前进超过一页 - 有可能吗?

iOS - 通过我们的用户交互定期更新 UILabel 文本

java - 我正在使用 @PropertySource 和 @ConfigurationProperties 的组合,但我想用外部属性文件覆盖它们

iphone - 逐步通过 plist 获取信息

iphone - iPhone 中这些控件的替代品有哪些

导航栏中的 iOS 搜索栏

java - 从属性文件加载 xml

javascript - 有多少种方法可以查看您手动添加到函数的所有属性? JavaScript。 JS