访问实例variables的语法? (目标C)

在Objective-C中访问实例variables的正确语法是什么?

假设我们有这个variables:

@interface thisInterface : UIViewController { NSMutableString *aString; } @property (nonatomic, retain) NSMutableString *aString; 

而且它是合成的。

当我们想要访问它时,我们首先要分配并初始化它。 在Objective-C编程了大约一个月之后,我看到了两种不同的语法forms。 我已经看到人们只是简单的aString = [[NSMutableString alloc] initWithString:@"hi"] ,他们在那里分配string; 我也看到人们用self.aString开始,然后他们开始初始化他们的伊娃。 我想我只是想弄清楚什么是初始化一个实例variables的最合适的方式,因为在前面的例子中,我收到了EXC_BAD_ACCESS错误。 在预先self. 虽然,它并没有出现。

原谅我,如果这是一个重复的问题,但在阅读了一些post后,这让我好奇。 我正在尝试使用Objective-C来学习正确的语法,因为我更喜欢正确而不是马虎。

如果你已经声明了一个属性,然后在.m文件中把它合成,你可以像下面这样设置它:

 self.aString = @"hi"; // or [[NSMutableString alloc] initWithString:@"hi"]; 

使用self.varName可以充分利用你的属性声明实际上做的事 – 它处理新值的retain (因为你的属性有retain属性),为你释放旧值等等。

如果你只是这样做:

 aString = someValue; 

…你可能正在泄漏aString的原始值,因为没有使用self.aString你直接访问variables而self.aString通过属性。

请注意self->varNameself.varName之间的区别

首先是指针访问。 第二个是财产访问。

为什么这很重要? 指针访问是直接的。 另一方面,财产访问使用getter和setter( @synthesized他们是否被@synthesized )。 此外,作为一个方便,@synthesized访问器照顾你的内存pipe理(即当使用self.varName = ...; ),而varName = ...; 只做它所说的,即赋值 – >(这里有你可能得到的EXC_BAD_ACCESS错误的解释)。

在句法上,两种forms都是正确的。 如果你想更好地交stream意图,当你想直接使用指针时使用self.varName self->varName当你想利用self.varName时使用self.varName

这里有所有可能的组合(我认为)当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 

与第二种方法相同。

 self.aString = [[NSMutableString alloc] init]; //BAD!! 

不好,因为你保留了两次,所以会导致内存泄漏

6

 self.aString = [[NSMutableString string]; //******GOOD!****** 

这可能是最安全的。 它将被属性设置器保留,并且由于您使用的是setter,因此任何可能由aString指向的其他对象都将被正确释放

7

 self.aString = [[NSMutableString string] retain]; //BAD 

这保留了两次。

8

 self.aString = [[[NSMutableString alloc] init] autorelease];//Ok 

这也是好的,但我会用方便的方法,而不是这个长的方法:)

要小心,如果你知道你在做什么,#1和#3的select是非常好的。 实际上我比#6更频繁地使用它们

我个人更喜欢使用self. 句法。 它只是让它更容易确定它的一个实例variables,而不是当前作用域中的NSAutoreleasePool被耗尽时将会丢失的其他variables。 但是,使用这两种方法是正确的,如果您收到EXC_BAD_ACCESS错误,则不是因为您在不使用self.情况下访问它self. 。 你说的是正确的,你必须分配它,无论你select访问variables,保持一致,否则你会收到错误。

我希望这有帮助。

initdealloc和访问器本身之外,始终使用访问器。 这样做会为您节省很多像您所描述的头痛。 另外,将你的ivars命名为不同于你的属性( _foofoo_mFoo ,但不是foo )。

self.foo[self foo]完全相同。 我把这个方法叫做fooself.foo = x[self setFoo:x] 。 它调用方法setFoo: 如果将foo属性合成为retainvariables,那么这看起来像这样:

 @synthesize foo = foo_; - (void)setFoo:(id)value { [value retain]; [foo_ release]; foo_ = value; } 

这正确地释放foo_的旧值,分配一个新值并保留它。

foo = x (假设foo是一个ivar)不会调用任何方法。 没有。 它只是将x中指针的值赋给foo的指针。 如果foo指出某些被保留的东西,它会被泄漏。 如果您分配的新值没有保留,则稍后会崩溃。

解决这个问题的方法是在任何时候总是使用访问器。

无论是。

使用点语法更清晰(对一些),它编译为等效。 即self.iVar[self iVar]相同, self.iVar = aValue[self setIVar:aValue];

self.aString[self aString]一个语法糖。 合成属性只需创build-aString-setAString:方法(取决于您select的属性,而不是微不足道的作用)。

现在的问题是是否使用. 符号。 我build议你不要使用它。 为什么? 首先知道Objective-C只是C的一个附加。这意味着每个有效的C代码也是一个有效的Objective-C代码。

现在看看他们用点符号做了什么。 最后的声明不再成立。 你不会区分对C结构域的访问和发送objective-c方法。

所以请不要使用点符号。 更喜欢使用[self ..]。