如何解决访问实例变量的语法? 目标C
| 在Objective-C中访问实例变量的正确语法是什么? 假设我们有这个变量:@interface thisInterface : UIViewController {
NSMutableString *aString;
}
@property (nonatomic,retain) NSMutableString *aString;
并且它是合成的。
当我们要访问它时,我们首先要分配和初始化它。在Objective-C中编程大约一个月以来,我已经看到了两种不同形式的语法。我见过人们只是简单地做aString = [[NSMutableString alloc] initWithString:@\"hi\"]
,他们就这样分配字符串。我还看到人们以ѭ2开始,然后开始初始化他们的ivar。我想我只是想弄清楚初始化实例变量的最正确方法是什么,因为在前面的示例中,我从中收到了EXC_BAD_ACCESS错误。在加上“ 3”之后,它没有出现。
如果这是一个重复的问题,请原谅我,但是在阅读了有关SO的一些帖子后,这使我感到好奇。我正在尝试使用Objective-C学习正确的语法,因为我更喜欢适当而不是草率。
解决方法
如果您声明了一个属性并在.m文件中将其“ 4”表示,则只需按如下所示进行设置:
self.aString = @\"hi\"; // or [[NSMutableString alloc] initWithString:@\"hi\"];
使用self.varName
可以利用属性声明的实际作用,它可以处理新值的保留(因为属性具有retain
属性),为您释放旧值等。
如果您只是这样做:
aString = someValue;
...您可能正在泄漏aString
中的原始值,因为不使用self.aString
便是直接通过属性访问变量。
, 注意self->varName
和self.varName
之间的区别
首先是指针访问。第二个是属性访问。
为什么这么重要?指针访问是直接的。另一方面,财产使用权则利用了吸气剂和吸气剂(不论是否为@synthesized
)。此外,为方便起见,@synthesized访问器会为您处理内存管理(即,使用self.varName = ...;
时),而ѭ15only只会执行其所声明的内容,即赋值->(这里有EXC_BAD_ACCESS错误的解释,您可能会得到)。
从语法上讲,两种形式都是正确的。如果您想更好地传达意图,请在直接使用指针时使用ѭ11,而在要使用@property
便利时使用ѭ6。
, 这是所有可能的组合(我认为)
仅当aString
属性具有retain
属性时,OK和BAD才正确:
@property (nonatomic,retain) NSMutableString *aString;
所以:
1个
aString = [[NSMutableString alloc] init]; //OK:
可以,但是仅在aString未指向无效对象的情况下,否则您将丢失对该对象的引用,并且它将泄漏,因为您将无法到达该对象以释放它。
2
aString = [NSMutableString string]; //BAD
不好,因为您假设要保留aString(如您那样声明),而不是保留它,将来肯定会得到EXC_BAD_ACCESS
3
aString = [[NSMutableString string] retain]; //OK
与第一种方法相同,只有在aString未指向有效对象的情况下才有用。但是,我将使用第一个。
4
aString = [[[NSMutableString alloc] init] autorelease];//BAD
与第二种方法相同。
5
self.aString = [[NSMutableString alloc] init]; //BAD!!
不好,因为您将其保留了两次,因此将导致内存泄漏
6
self.aString = [[NSMutableString string]; //******GOOD!******
这可能是最安全的。它将由属性设置器保留,并且由于您使用的是设置器,因此可能会适当释放aString可能指向的任何其他对象。
7
self.aString = [[NSMutableString string] retain]; //BAD
这将保留两次。
8
self.aString = [[[NSMutableString alloc] init] autorelease];//Ok
这也可以,但是我将使用便捷方法代替这种长方法:)
请注意,如果您知道自己在做什么,那么#1和#3选项就非常好。实际上,我比#6更频繁地使用它们
, 我个人更喜欢使用self.
语法。它只是使确定它的实例变量变得容易,而不仅仅是确定当前范围内的其他变量(当耗尽其NSAutoreleasePool时将丢失的变量)。但是,同时使用这两种方法是正确的,并且如果您收到EXC_BAD_ACCESS错误,则不是因为您未使用self.
进行了访问。正确地说,您必须分配它,并且无论选择哪种方式访问变量,都必须使其保持一致,否则您将收到错误。
我希望这有帮助。
,除init
,dealloc
和配件本身外,请始终使用配件。这样做将为您节省很多麻烦,就像您描述的那样。另外,为您的个人名字命名与您的财产不同的名称(_foo
,foo_
,mFoo
,而不是foo
)。
self.foo
与ѭ39precisely完全相同。我将方法称为“ 37”。 self.foo = x
与[self setFoo:x]
完全相同。它调用方法“ 43”。如果您将属性ѭ37synthesized合成为retain
变量,则该内容类似于:
@synthesize foo = foo_;
- (void)setFoo:(id)value {
[value retain];
[foo_ release];
foo_ = value;
}
这样可以正确释放foo_
的旧值,分配一个新值并保留它。
foo = x
(假设foo
是一个ivar)不调用任何方法。没有。它只是将x
中的指针值赋给foo
中的指针。如果ѭ37指向保留的内容,则表示已泄漏。如果您分配的新值未保留,您将在以后崩溃。
解决方案是始终使用访问器。
, 要么
使用点语法(在某些情况下)更干净,并且可以编译为等效语法。即self.iVar
与[self iVar]
相同,self.iVar = aValue
与[self setIVar:aValue];
相同
, self.aString
是to58ѭ的语法糖。合成属性只需创建-aString
和-setAString:
方法(取决于您选择的属性,而不是普通的影响)。
现在的问题是是否使用ѭ61表示法。我建议您不要使用它。
为什么?首先要知道Objective-C只是对C的补充。这意味着每个有效的C代码也是有效的Objective-C代码。
现在看看他们用点符号表示了什么。最后一条语句不再成立。您将不会区分对C结构字段的访问和发送Objective-C方法。
因此,请不要使用点符号。优先使用[self ..]。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。