在iPhone上工作,在经历了许多令人头疼的问题和内存问题之后,我从其他示例中意识到,我们没有必要为我们在头文件中定义的每个实例变量创建@属性。实际上,我发现在类中的任何地方使用ivars都很容易分配和释放它,因为@properties我必须使用autorealese,否则我就会遇到严重的问题,并且要注意分配的方式。
例如,对于下面的对象,@properties(保留/复制..)在许多示例中没有在头部中使用;
{
NSURLConnection *connection;
NSMutableData *xmlData;
NsMutableString *string
} 但对于某些字符串或对象类型使用@properties,我知道当我们设置@property时,cocoa会创建一些setters来处理对象的重新分配和保留。但似乎对于xmlData或连接实例变量,我们不需要它们,它们的工作方式是这样的。
在决定是创建@property还是只使用简单的ivars时,有没有一些我可以记住的参考指南?
我在使用属性时唯一的问题不是因为我懒于定义它,但是当我在代码中仔细地分配和初始化它们时,我必须使用autorelase,并且感觉我不能控制何时释放重置并再次分配它,它让我又多了一件事要担心何时、何时以及如何释放、重置它。我发现anything..or我可以随时随地轻松地分配和释放,而不用担心ivars,我在这里遗漏了其他东西。
Tnx
发布于 2011-08-04 23:17:42
似乎仍然有一些关于属性的误解。
我们不需要为我们在头文件中定义的每个实例变量创建@
对,是这样。您可以在实现文件中直接使用私有实例变量。但是,由于合成的属性附带了免费的内存管理,因此您最好利用这一点。我的经验法则是直接使用ivar,直到我第一次发现自己在写:
[ivar release];
ivar = [newIvar retain];正如萨姆所说,如果使用iVar == newIVar,就已经有了一个潜在的bug。在这一点上,我从直接使用ivars切换到创建属性。但是,我将新属性的声明放在实现文件的class extension中。这意味着该属性正式不是公共接口的一部分(如果意外使用,将导致编译器警告)。
当我们设置@property cocoa时,
会创建一些setters,这些getter处理对象的重新分配和保留。
实际上,不是。@属性只是声明了一个属性。为了自动生成getter和setter,您需要@synthesize它。你也可以编写你自己的setter和setter,它们甚至不需要引用真正的ivar。
从技术上讲,您不应该在init或dealloc方法中使用该属性,因为子类可能已经覆盖了它们,或者(在dealloc中)您可能会触发KVO通知。
来自Sam的回答和评论
如果您无论如何都想要一个属性,则可以在实现文件的顶部使用私有接口
正如我上面所说的,私有类别已经被类扩展所取代(这与类扩展非常相似,但允许您将方法的实现放在主类实现中)。
如果您想要获得使用点符号速记的好处,请使用
我们中的一些人会争辩说,点符号没有任何好处。这是对结构成员语法的一种无端和不必要的污染。但是,点符号与@property声明无关。您可以对任何访问器使用点表示法,无论它们是如何声明的,只要它们遵守模式-foo和-setFoo:
发布于 2011-08-04 21:40:13
只为需要从类外部访问的变量创建属性。内部使用的任何类变量都不需要定义getter/setter。
一般来说,丰富的属性表示高耦合和差的封装性。您应该限制您的类在接口中公开的变量。
编辑以回应评论:
使用属性而不是直接访问可能是的首选,因为它为您提供了简单的内存管理。例如:
// interface
@property (retain) Object *someVar;
// implementation
self.someVar = otherVar;等同于
// implementation
if (_someVar != othervar)
{
[_someVar release]
_someVar = [otherVar retain];
}但是,您不应该在接口中不必要地公开var,因为它会让人们以错误的方式使用类。
如果您无论如何都想要一个属性,可以在实现文件的顶部使用私有接口
@interface TheClass(Private)
// private stuff
@end发布于 2011-08-04 22:24:45
长期以来,直接访问ivars已经成为一种习惯。也就是说,尽管许多属性都是类,然后属性提供了保护,防止保留/释放问题,但从同一个类中可以很好地处理IMO。
然而,最好将大多数ivars封装到属性中,特别是那些具有保留/释放语义的属性,但也包括那些需要特殊处理的属性,即您为其编写自己的处理程序,而不是使用合成的处理程序。这样,你就可以过滤对某些ivars的访问,或者甚至创建没有任何后备存储的属性,这些属性只是其他属性的“别名”,例如,Angle类具有度属性,该属性以度为单位提供角度,弧度属性以弧度表示相同的角度(这是一个简单的转换),或者是一个必须进行字典搜索才能找到它的值的属性,等等。
在Delphi (AFAICT)中,它是最早将属性作为语言构造的语言之一,习惯上将所有的ivar都包装在属性中(但不是所有的都必须是公共的),并且有许多这样的“不真实”(我在这里故意避免使用术语“虚拟”)属性,即那些只在代码中实现的属性,而不仅仅是ivar的getter和setter。
属性提供encapsulation,abstraction和一定程度的保护,防止某些常见的错误,这就是为什么它们比直接访问ivars,IMO更受欢迎的原因。
加法
声明和实现(通过@synthesize或者使用自定义的setter和getter)公共属性为每个 ivar是没有意义的。只公开暴露别人可能需要的东西。内部状态也可以通过属性向您自己的代码公开,但这应该通过实现文件中的私有或空类别来完成。这样,您就可以自动处理保留/释放,并且仍然不会向公众公开它们。
https://stackoverflow.com/questions/6942439
复制相似问题