Objective c 我是否应该在带有ARC的init方法中引用self.property?

Objective c 我是否应该在带有ARC的init方法中引用self.property?,objective-c,ios5,initialization,automatic-ref-counting,reference-counting,Objective C,Ios5,Initialization,Automatic Ref Counting,Reference Counting,一个简短的问题 如果我有一个属性和一个使用相同名称声明的ivar: 在.h文件中: (Reminder*)reminder; @property(nonatomic,strong)(Reminder*)reminder; 在.m文件中,如果使用ARC,我应该使用ivar还是init方法中的属性 - (id)initWithReminder:(Reminder*)reminder_ { self = [super init]; if (self) { remind

一个简短的问题

如果我有一个属性和一个使用相同名称声明的ivar:

在.h文件中:

(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;
在.m文件中,如果使用ARC,我应该使用ivar还是init方法中的属性

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
    }
    return self;
}
或者我应该使用该属性获得自动引用计数的好处,如下所示:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        self.reminder = reminder_;
    }
    return self;
}

我不确定在对象初始化的哪一点上,可以使用点表示法访问属性。

在部分构造的状态下使用直接访问,而不考虑弧:

- (id)initWithReminder:(Reminder*)reminder_ {
    self = [super init];
    if (self) {
        reminder = reminder_;
        // OR
        reminder = [reminder_ retain];
    }
    return self;
}
这是因为
self.
将触发其他副作用,例如键值观察(KVO)通知,或者您的类(显式)实现或子类重写
setwhater:
——这可能会将您部分初始化的实例暴露给其他API(包括它自己的API),正确地假设他们正在处理一个完全构造的对象

您可以手动验证类是否能够在部分初始化状态下运行,但这需要大量维护,而且(坦率地说)在其他人想要对您的类进行子类化时是不切实际或不可能的。它需要大量的时间和维护,而且这样做没有实质性的好处,特别是如果您试图将该方法作为惯例使用

因此,保证正确性的统一方式是在部分构造状态下使用直接访问,并避免使用访问器

注意:我使用“部分构造”,因为初始化只是图片的一半<代码>-dealoc也有类似的警告

关于为什么在部分构造状态下使用直接访问(ARC | | MRC)的更多详细信息,请参见此处:

不,您不应该

您可以找到为什么
苹果也建议不要这样做

我不确定在对象初始化的哪一点上,可以使用点表示法访问属性

由于点表示法仍然是一种Objective-C方法(实际上是ObjC方法下的一种C方法),因此点表示法或调用该方法是完全安全的,因为该方法可以处理内存中处于任何状态的底层类型。 关于避免使用未初始化(可能)车库内存段的常规规则仍然适用。这是在init中使用ivar的最大动机

但是,如果您的方法(getter | setter)能够正确地使用内存段(与读取之前是否先写入内存段无关),那么一定要在init方法中使用getter。 惰性getter利用它将初始化的指针以“nil”开头的假设来决定是否执行初始化。如果您不能假定内存的初始内容,那么初始化ivar可能是最安全的方法


如果方法能够在这种情况下正确运行,为什么在init中永远不使用setter或getter呢?

如果使用synthesis(我猜是这样),并且使用现代编译器(我猜是因为ios5),则不需要声明ivar,objective-c会自动为您声明。(这不是你问题的答案,只是一个旁注)。知道这一点是件好事,到目前为止,我一直为属性声明IVAR。是的,我使用默认名称@synthesis属性。我将告诉你与@choise相同的事情。我相信不管你是否使用这个属性,你仍然可以得到ARC的好处。你甚至不需要
@synthesis
当涉及到子类时,我有点困惑。如果我们不应该在init方法中使用self.propertyName,那么如何在子类的init方法中访问父类的属性?在子类中使用_propertyName表示未声明的变量,唯一的解决方案是使用self.propertyName。示例:@Zhang通常,您应该避免在初始值设定项中访问基类的属性。这种方法要求您的派生类了解其超类的实现,以及可以覆盖访问器实现的所有派生类。在objc中,您实际上可以调用(未初始化的)派生类的重写访问器方法。因此,您可以通过以下方式避免这种头痛/风险:遵循上述建议,提供更合适的初始值设定项,在完全构造的实例上使用访问器,使用不太复杂的类型(组合),方便的构造函数,等等@Zhang我认为从子类“init”的超类调用属性是安全的。当您到达子类“init”的“body”时,超类“init”应该已经完成了。这意味着,超类本身(或者至少应该,如果写得正确的话)已经完全初始化了。因此,访问其(=超类)属性应该是安全的——即使您在子类中重写了该属性。问题是在超类中访问init中的属性时。在这种情况下,如果您重写子类中的setter,您可能会使用部分初始化的对象到达那里。@justin好的,那么当我将UITableViewCell子类化并想在初始化时添加一些自定义UIView作为其contentView的子视图时,我应该做什么来代替:[self.contentView addSubview:someSubview]@justin如果我在代码中构造UITableViewCell子类(你不能说它是禁止的),那么awakeFromNib就不是一个选项。在我看来,在这种情况下使用延迟初始化是解决问题的简单方法。我只在逻辑上使用惰性初始化(例如,当非惰性初始化是瓶颈时,而不是这里的情况)-不是为了坚持其他一些(不相关的)规则。。。但好的,我认为我们有两种不同的方法和优先权,我们适用于我们的代码:)