在objective-c类中引用实例变量之间的区别是:
self.myIvar
和
myIvar
如果它已在标题中声明为属性并合成?
答案 0 :(得分:3)
如果你引用self.myVar,它将使用头文件中声明的@property。
例如
@property(nonatomic, retain) Class *myClass;
如果你有
myClass = [ [ Class alloc ] init .... ];
保留计数 1 但是如果你使用
self.myClass = [ [ Class alloc ] init .... ];
由于保留属性,保留计数将 2 。
如果你设置setter ||就是一样的@property中的getter方法。
答案 1 :(得分:3)
在objective-c类中引用实例变量之间的区别是:
self.myIvar
和
myIvar
如果它已在标题中声明为属性...
简单:前者不引用实例变量。
它指的是名为myIvar
的属性。同样,后者指的是实例变量而不是属性。
该属性当然是错误名称,因为属性和实例变量不一定彼此有任何关系,实际上属性甚至不需要由实例变量支持。
尝试访问self.myIvar
与发送self
该属性的getter消息完全相同。也就是说,这两个陈述:
foo = self.myIvar;
foo = [self myIvar];
完全相同。
同样,尝试分配到self.myIvar
与发送self
setter消息完全相同。这两个陈述:
self.myIvar = foo;
[self setMyIvar:foo];
完全相同。
相比之下,参考实例变量myIvar
(无self.
):
foo = myIvar;
myIvar = foo;
就是这样:访问变量; 不再是。
这意味着很多。
存取者,特别是制定者,往往会产生副作用。例如,如果属性声明为retain
,则为其合成的setter将释放属性的旧值并保留新值。同样,如果属性声明为copy
,则合成的setter将释放旧值并复制新值。
由于对财产的转让:
self.myProperty = foo;
是一个访问者消息,“赋值”将导致旧值被释放并且新值被保留/复制。
对变量的赋值:
myIvar = foo;
只不过是对变量的赋值,不会这样做。如果您拥有myIvar
的旧值,那么您只是泄露了它,如果您还没有拥有新值,那么您仍然不拥有它,这意味着它可能会在您仍然持有时死亡在它上面,导致后来崩溃。 (见the Memory Management Programming Guide。)
尽管两者看起来很相似,但它们非常非常不同。
作为一般规则,您应该在除init
方法和dealloc
方法之外的任何地方使用属性,并在这些方法中直接访问实例变量(其中包含实例变量)。 (同样,访问者可能有副作用;您可能不希望在半初始化或半释放对象中出现这些副作用。)
......并合成了?
那没关系。 @synthesize
只是告诉编译器如何实现属性访问器的三种方法之一:
@synthesize
:编译器,您实现它们。@dynamic
:不要担心,编译器;我的超类将在运行时动态提供访问器。 (在NSManagedObject的子类中最常见。)- (Foo *) myProperty { … }
/ - (void) setMyProperty:(Foo *) newFoo { … }
:以下是我对访问者的实现。未能为属性执行一项或多项操作会从编译器和某些运行时异常中获得警告,因为您从未实际为访问者声明过(通过声明@property
})你声明了实例会有。
答案 2 :(得分:1)
不同之处在于ivar
只是指向内存中某个位置的变量,而self.ivar
则调用setter(在self.ivar = x
的情况下)和getter(对于{{1} }}) 方法。 IE,在这些语句中,x = self.ivar
分别被转换为self.ivar
和[self setIvar:value]
。然后,这些方法可以代表您处理诸如保留/释放和任何特定于类的行为之类的事情,实际上是通过直接引用[self getIvar]
来实现的。 ivar
关键字会自动生成这些getter和setter方法,以便您减少样板代码。
因此,@synthesize
是内存中您的对象可以存储内容的位置,ivar
将类方法包装在内存中的该位置以管理对它的访问。请注意,在初始化对象时,通常最好直接设置ivars,以避免对不完全形成的对象造成可能的奇怪行为。
答案 3 :(得分:0)
请注意,在那些自定义访问器中,您几乎必须省略self。部分是为了避免无休止的递归,例如如果你有一个名为s的字符串属性,那么setter就可以了(顺便说一下,这类似于@synthesize时生成的内容):
-(void)setS:(NSString *)newVal
{
if(newVal == s) return;
[s release];
s = [newVal retain]; //if you use self.s here, setS will be called again
}
答案 4 :(得分:0)
self.ivar
调用稍后可以更改或添加的属性方法,也可以执行一些内存管理。例如,你可以设置self.ivar也改变ivar2,增加ivar3,边界检查ivar4,向object5发送消息,释放object6,播放sound7等。
ivar
只是在内存中读取或写入一些位。