2014-06-18 162 views
2

我倾向于经常使用self.property在访问变量时我的Objective C代码,据我所知,这使用了getter/setter方法(显式编码或自动生成)。为什么initWithCoder需要self.property?

另一位编码员最近告诉我,最好在整个代码中使用_property。但我的理解是,_property实际上只用于init和dealloc方法。

今天我在一些使用initWithCoder的代码中发现了一个错误。我在initWithCoder方法中使用了_property,并且必须将其更改为self.property。这是在设置NSData对象时。这里是原代码:

@property (nonatomic, strong) NSData *data; 

- (id)initWithCoder:(NSCoder *)decoder { 
    self = [super init]; 
    if (!self) { 
     return nil; 
    } 
    _data = [decoder decodeObjectForKey:@"data"]; 
    return self; 
} 

我只好改成这样,才能得到它的工作:

@property (nonatomic, strong) NSData *data; 

- (id)initWithCoder:(NSCoder *)decoder { 
    self = [super init]; 
    if (!self) { 
     return nil; 
    } 
    self.data = [decoder decodeObjectForKey:@"data"]; 
    return self; 
} 

我的问题是 - 为什么的initWithCoder例外吗?如果通常认为最好在init方法中使用_property,那么为什么initWithCoder不同?

现在好像一般的规则是:

使用self.property除了在初始化/ dealloc的方法,其中_property应使用(除利用initWithCoder,应当使用self.property)。

这是正确的吗?

+1

我无法看到'initWithCoder:'代码'self.property'在'_property'不会的时候会有效。你明白'self.property'使用这个属性的_setter_来初始化它,而'_property'不会绕过setter,而是直接初始化属于你属性的_instance variable_这似乎奇怪:/ – nburk

+0

当你说“让它工作”时,你遇到了什么错误。我没有看到原始的基于ivar的init有问题。编码员告诉你独占使用ivars是不正确的;这不是最佳做法。有一段时间ObjC社区内存在更多的分歧,但是Apple最终证明你应该使用除init和dealloc之外的访问器。 –

+0

我刚做了一个测试,它可以同时处理'_data'和'self.data'。您定位的是哪个版本的iOS?更早的版本不会自动生成属性data的'_data'变量。 – Daniel

回答

1

我不认为这是一般的事实,您必须使用initWithCoder:中的属性。我在initWithCoder:中使用ivar访问的代码很多(并且已经看到很多),如果这可能有助于提示。

如果您没有使用ARC,那么您的实现设置_data会产生问题,因为该对象很快会被自动回复。但在ARC下你的代码是正确的。

所以,我倾向于认为不同的事情导致了你的情况。例如,如果您使用KVO,那么您应该使用属性,否则不会生成与KVO相关的通知。您应该提供更多信息,说明究竟是什么导致您认为_data的分配是问题的原因,以及该问题在代码的其他部分中的可见影响。

+0

这很奇怪。我检查了应用程序,它使用ARC。我查看了构建阶段中的所有模块,没有一个设置为非ARC。是什么让我认为这是_data的用法,只需将该行更改为self.data即可使应用程序正常工作。否则,应用程序会在[NSKeyedUnarchiver unarchiveObjectWithFile:cachePathForKey]之后崩溃;声明,当我尝试对数据做些什么的时候。它在initWithCoder中不会崩溃,它在从NSKeyedUnarchiver语句返回后崩溃。 – Darren

+0

你会得到什么样的碰撞?你能不能从控制台发布崩溃日志?当你说它在“之后”崩溃时,你的意思是它没有得到下一个陈述吗?完整的'unarchiveObjectWithFile'看起来如何? – sergio

+0

看起来这是从unarchiveObjectWithFile返回时释放对象的问题。当我使用MyCachedObject创建我的对象* tmp = [NSKeyedUnarchiver unarchiveObjectWithFile:cachePathForKey];它崩溃。但是,如果我分配对象,然后调用unarchiveObjectWithFile,像这样:MyCachedObject * tmp = [[MyCachedObject alloc] init]; tmp = [NSKeyedUnarchiver unarchiveObjectWithFile:cachePathForKey];有用。似乎该对象不会在通话返回时保留。 – Darren