这是一个月前我正在读一条关于这一点。我不确定,但我认为如果我调用self.myInstanceVariable然后它会自动使用getter / setter,但是如果我直接调用myInstanceVariable = @“Foo”,那么我会绕过任何getter / setter ,真的,非常糟糕。对/错?
编辑:我在XCode中试过这个。
实现如下:
@implementation Test
@synthesize name;
+ (Test*)testWithName:(NSString*)name {
Test* test = [self alloc];
test.name = name;
return [test autorelease];
}
- (void)setName:(NSString*)newName {
NSLog(@"SETTER CALLED!!");
if(name != newName) {
[name release];
name = [newName retain];
}
}
- (NSString*)name {
NSLog(@"GETTER CALLED!!");
return name;
}
- (void)doWrongThing {
NSString *x = name;
NSLog(@"doWrongThing: %@", x);
}
- (void)doRightThing {
NSString *x = self.name;
NSLog(@"doRightThing: %@", x);
}
测试代码如下:
Test *t = [Test testWithName:@"Swanzus Longus"];
//NSLog(@"%@", t.name);
[t doWrongThing];
[t doWrongThing];
[t doWrongThing];
[t doRightThing];
所以在用另一种方法启动这段代码后(我只使用现有的项目;)),我在控制台中收到了这个输出:
2009-05-01 19:00:13.435 Demo[5909:20b] SETTER CALLED!!
2009-05-01 20:19:37.948 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.950 Demo[6167:20b] GETTER CALLED!!
2009-05-01 20:19:37.965 Demo[6167:20b] doRightThing: Swanzus Longus
就像你看到的那样,你必须使用self.instanceVariableName来使用getter和setter(或者用括号进行调用,也可以使用)。
混淆警报:如果您在要从中访问实例变量的对象的方法中进行攻击,则必须仅使用self。从外部来看,当你调用someObjectPointer.someInstanceVariable时,它会自动访问getter和setter(是的,我也试过了)。
只是觉得有人会对一个小案例研究感兴趣;)
答案 0 :(得分:9)
这是正确的。如果您直接使用该变量,绕过getter / setter可能会产生错误。吸气剂/设定器可以负责保留和/或释放物体以及其他物体。这可能导致崩溃/内存泄漏等。
如果您知道您绕过了getter / setter并采取了正确的预防措施,那么直接访问变量没有任何问题。
答案 1 :(得分:3)
Jesse有一些很好的见解(给你+1,先生)。
我认为直接显式调用底层成员变量(因此绕过getter / setter)的唯一情况是我自己编写了getter / setter,并且确切地知道它是什么而且没有做什么,以及99%的时间是我刚刚在构造函数中初始化成员。
答案 2 :(得分:2)
请阅读文档
首先,这是不正确的
Test* test = [self alloc];
正确
Test* test = [[self alloc] init];
其次,如果你写
@synthesize name;
方法
- (void)setName:(NSString*)newName
- (NSString*)name
将自动生成(!! dot-syntax只是syntax-sugar !!)
第三,写作时
myvar.itInstanceVariable
它转换为
[myvar itInstanceVariable]
和
myvar.itInstanceVariable = newValue
转换为
[myvar setItInstanceVariable:newValue]
关于您的评论,当您以这种方式申报财产时
@property(nonatomic, retain) MyType *myVar;
并写入实现
@synthesize myVar
它创建了两个方法
- (MyType*)myVar {
return myVar;
}
- (void)setMyVar:(MyType*)newVar {
if (myVar != newVar) {
[myVar release];
myVar = [newVar retain];
}
}
所以你不必担心重新发布/释放
答案 3 :(得分:1)
是的,属性语法调用setter。在几乎所有情况下,这都是您想要的,因为它默认正确处理大量内存管理。此外,属性名称,ivar名称和getter / setter名称也可以不同,因此您可能会发现它看起来不像self.myInstanceVar
的情况。
另外,作为附注,您可能已经或可能不知道这一点,但如果您打算编写所有的存取方法,那么合成属性是没有意义的。