ObjectiveC ivars或@property

在iPhone上工作了很多头痛和内存问题之后,我从其他例子中发现,我们不需要为每个在头文件中定义的实例variables创build@properties。 实际上,我发现ivars容易分配和释放它,因为我使用autorealese @properties,或者我有严重的问题,并becareful如何分配..

例如,对于下面的对象,在许多示例中,标题中不会使用@properties(retain / copy ..);

{ NSURLConnection *connection; NSMutableData *xmlData; NsMutableString *string } 

但对于一些string或对象types使用@properties,我知道当我们设置@property cocoa创build一些setter getter来处理这些对象的关联和保留。 但似乎是xmlData或连接实例variables,我们不需要这样做,他们这样做他们的工作。

在决定是否创build@ property或仅使用简单的ivars时,是否可以记住一些参考指南?

我使用属性时唯一的问题不是因为我懒惰定义它,但是当我仔细分配和初始化他们在代码中,我不得不使用autorelase,并不觉得我有控制何时释放重置和再次分配,它给了我更多的担心,什么时候以及如何释放,重置它。 我发现ivars我可以随时随地轻松分配和释放,而无需担心任何事情..或者我在这里错过了其他的东西。

TNX

似乎还有一些关于房地产的误解。

我们不需要为每个我们在头文件中定义的实例variables创build@properties

正确。 您可以直接在实现文件中使用私有实例variables。 但是,由于合成属性具有可用的内存pipe理function,因此您可以充分利用。 我的经验法则是直接使用伊娃,直到我第一次发现自己写作:

 [ivar release]; ivar = [newIvar retain]; 

正如山姆所说,如果iVar == newIVar话,那里已经存在一个潜在的bug。 这是我从使用ivars直接创build一个属性的angular度。 但是,我把这个新属性的声明放在了实现文件中的类扩展中。 这意味着该属性不是公共接口的一部分(如果意外使用,会导致编译器警告)。

当我们设置@property cocoa创build一些setter getter来处理对象的inheritance和保留。

其实没有 @property只是声明一个属性。 为了自动生成getter和setter,你需要@synthesize它。 你可以写下你自己的getter和setter,甚至不需要引用真正的ivar。

从技术上讲,不应该在init或dealloc方法中使用属性,因为子类可能已经覆盖了它们,或者(在dealloc中)可能会引发KVO通知。


从山姆的回答和评论

如果你需要一个属性,你可以在实现文件的顶部使用一个私有接口

正如我上面所说的那样,私有类别已经被类扩展(已经足够接近相同的东西,但是允许你把这些方法的实现放在主类实现中)过时了。

如果你想使用点符号简写的好处

我们有些人会认为点符号没有好处。 这是对结构成员语法的无偿和不必要的污染。 但是,点符号与@property声明没有关系。 对于任何访问者,无论声明如何,都可以使用点符号,前提是他们遵守模式-foo和and -setFoo:

仅为需要从类外部访问的variables创build属性。 任何在内部使用的类variables都不需要定义getter / setter。

一般来说,丰富的性质表明高耦合和差的封装。 你应该限制你的类在界面中暴露的variables。

编辑回应评论:

使用直接访问属性可能是首选,因为它可以让您轻松进行内存pipe理。例如:

 // interface @property (retain) Object *someVar; // implementation self.someVar = otherVar; 

是相同的

 // implementation if (_someVar != othervar) { [_someVar release] _someVar = [otherVar retain]; } 

但是,您不应该在界面中不必要地暴露variables,因为它会打开课程,让人们以错误的方式使用。

如果你想要一个属性,你可以在实现文件的顶部使用一个私有接口

 @interface TheClass(Private) // private stuff @end 

首先,让我说,山姆的答案是完整的,国际海事组织,并给你明确的指导方针(从我+1)。

我使用属性时唯一的问题不是因为我懒惰定义它,但是当我仔细分配和初始化他们在代码中,我不得不使用autorelase,并不觉得我有控制何时释放重置和再次分配,它给了我更多的担心,什么时候以及如何释放,重置它。 我发现ivars我可以随时随地轻松分配和释放,而无需担心任何事情..或者我在这里错过了其他的东西。

你不应该担心在下面的习惯用法autorelease

 self.stringProperty = [[[NSString alloc] initWith...] autorelease]; 

因为这是事情的意图工作的方式;

编辑:[上述声明有几个部分:

  1. 对象被分配和初始化(保留计数为1);

  2. 立即,分配的对象也是autoreleased ; 这意味着对象将在控制stream回到主循环时自动释放(或多或less);

  3. 在同样的语句中,分配的对象被分配给一个保留的属性self.stringProperty ; 这具有(再次)增加保留计数的效果;

所以, autorelease确实增加了一些“模糊性”,因为这个对象会在你不知道的时候被释放(不过很快就会发生),但是分配给retain属性会增加保留的数量,所以 完全控制对象的生命周期。]

如果你不喜欢autorelease你总是可以使用一个构造函数的方法,它会返回一个自动释放的对象,如果可用的话:

 self.stringProperty = [NSString stringWith...]; 

或直接分配给伊娃:

 stringProperty = [[[NSString alloc] initWith...] autorelease]; 

因为通过直接访问伊娃你是绕过了二传手和吸气剂。 无论如何, 只有在这种情况下(恕我直言),以避免含糊不清。

更一般的说, autorelease毛刺是使用属性直接访问ivars的唯一缺点。 剩下的就是国际海事组织,只有在许多情况下才能拯救你的生命,如果不是你的生命,泄漏或崩溃的好处。

没有任何东西可以直接访问ivars,在分配之前需要释放,或者在释放后不会忘记设置为nil等等,但是属性对于你来说会比较容易,所以我的build议是简单地使用它们并接受autorelease缺点。 只是把基本的“成语”弄对了。

长久以来一直直接访问ivars。 也就是说,国际海事组织,从同一类内部罚款,虽然许多属性是类,然后属性提供保护/释放问题的保护。

国际海事组织,但是,它是可取的封装大多数ivars属性,尤其是那些保留/释放语义,但也需要特殊处理,即你写你自己的处理程序,而不是使用合成的。 这样,你可以过滤对某些ivars的访问,甚至可以创build没有任何后备存储的属性,并且对其他属性只是“别名”,例如,具有度数属性的Angle类,用弧度表示相同angular度的弧度属性(这是一个简单的转换),或者必须执行字典search以查找其值的属性等。

在delphi(Delphi)中,(AFAICT)是第一个语言属性为语言结构的语言之一,习惯上把所有的ivars都包含在属性中(但并不是所有的都是公有的),而且有很多这样的“不真实的”我故意避免这里的“虚拟”属性,即只在代码中实现的属性,而不仅仅是一个伊娃的获取者和设置者。

属性提供封装抽象和一定程度的保护,防止某些经常发生的错误 ,这就是为什么他们比直接访问ivars,IMO更受欢迎。

加成

声明和实现(通过@synthesize或自定义设置器和getter) 每个伊娃的公共属性是没有意义的。 只公开暴露其他人可能需要的东西。 内部状态也可以通过属性暴露给自己的代码,但是应该在实现文件中使用私有或空类别来完成。 这样你就可以自动处理保留/释放,并且不会将它们暴露给公众。