带或不带实例变量的Objective-C属性

带或不带实例变量的Objective-C属性,objective-c,ios,class,properties,Objective C,Ios,Class,Properties,可能重复: 在获取或设置我正在编写的类的值时,我只对不需要任何实际验证的IVAR使用属性 Ex: @interface ClassB : NSObject { // No ivars } @property (nonatomic, retain) ClassA *obj; @property (nonatomic, retain) NSString *str; 每当我在类中调用这些方法时,我总是使用self.obj/self.str或[self-obj]/[self-str]。这

可能重复:

在获取或设置我正在编写的类的值时,我只对不需要任何实际验证的IVAR使用属性

Ex: 
@interface ClassB : NSObject
{
    // No ivars
}

@property (nonatomic, retain) ClassA *obj;
@property (nonatomic, retain) NSString *str;

每当我在类中调用这些方法时,我总是使用self.obj/self.str或[self-obj]/[self-str]。这样,为了设置对象的状态,您必须遍历属性,以便由编译器生成的getter和setter更仔细地管理引用。话虽如此,以这种方式创建类是否会遇到任何问题?此外,在没有ivar的情况下,@implementation文件中覆盖的“dealloc”方法是否需要任何“release”?

编译器会自动为您创建ivar,即使它没有在ivar列表中明确定义。它和属性列表中的名称相同。编译器现在不需要重复的定义行


如果您有需要发布的属性(IVAR),请执行此操作。

无需显式声明IVAR。我甚至建议省略它们,因为您应该始终通过访问器访问IVAR(正如您指出的那样)

您不会遇到任何问题,除非调试器不再直接捕获IVAR(它们不会很好地显示在您的控制台旁边),但这不是真正的问题

在dealloc方法中,您将不再需要释放它们。你需要做的是把它们置零

self.obj=nil

--

以下简要概述了属性属性的实际含义: (这是为了向您展示,当您在dealloc中为零一个变量时,就会发生释放)

分配

@属性(分配)NSString*名称

name = newValue;
if (name != newValue) {
   [name release];
   name = [newValue retain];
}
if (name != newValue) {
   [name release];
   name = [newValue copy];
}
保留

@属性(保留)NSString*名称

name = newValue;
if (name != newValue) {
   [name release];
   name = [newValue retain];
}
if (name != newValue) {
   [name release];
   name = [newValue copy];
}
复制

@属性(副本)NSString*名称

name = newValue;
if (name != newValue) {
   [name release];
   name = [newValue retain];
}
if (name != newValue) {
   [name release];
   name = [newValue copy];
}

如果您使用@synthesis指令创建属性访问器,编译器还将创建您在类声明中遗漏的任何IVAR。你仍然需要释放你的IVAR。过去,您无法直接访问合成IVAR,因此必须在-dealloc方法中使用属性setter,如下所示:

- (void)dealloc
{
    self.obj = nil;
    self.str = nil;
    [super dealloc];
}
不过,现在编译器将允许您直接访问合成的ivar,因此您可以释放它,而不是调用setter(这在-dealoc中是个好主意,在其他地方是个坏主意):


当您最终将代码转换为ARC(自动引用计数)时,这将发生变化,因为编译器将负责为您在-dealloc中发布ivars。大多数情况下,这意味着您的-dealloc实现可能会消失。

这不是真的,您不应该总是使用getter和setter。事实上,我们鼓励您直接在
init
dealloc
方法中访问IVAR,以避免潜在的副作用。此外,您仍然可以访问合成属性来释放它,例如
[\u myProperty release]
,这意味着您可以避免像前面提到的
dealloc
中那样的间接访问。上面提到的经验法则有一个例外:-)@Paul.s:合成的ivar没有前导下划线;它与属性的名称完全相同。是的,很抱歉,我没有足够的空间提及在ivar前面加前缀是很常见的,这样您就可以知道何时直接访问它们。在这个例子中,我应该在Objective-C编程语言中留下前缀:声明的属性|使用属性| dealoc:“如果您使用现代运行时并合成实例变量,那么您不能直接访问实例变量,因此必须调用访问器方法:-(void)dealoc{[self-setProperty:nil];[super-dealoc];}“这是更好的编程实践吗(在ARC代码之前)要将指针赋值为nil,还是释放?如果保留了对象,则必须释放它。仅将指针设置为nil会造成泄漏--您会丢失对该对象的引用,但从未释放该对象。如果要在释放指针后将其设置为nil,请放心。有些人希望看到指针更改为nil。这是错误的不过,oesn在-dealloc中没有太大帮助,因为无论如何,
self
都将被释放。在BJ荷马的例子中,由于他直接分配self.obj/self.str=nil,因为它们没有被释放,指针被分配给nil,是否会产生泄漏?如果他在做self.obj=nil,则会使用setter,它总是释放previous变量的内容(如果声明为“retain”),因此没有泄漏。啊,您的权利,因为setter将释放obj也指向的上一个对象,并将obj指向具有赋值的新内存位置(本例为nil),然后保留该位置作为所有权(在这种情况下,它不起任何作用,因为消息可以毫无例外地发送到nil)。