iPhone的内存pipe理(具体的例子/问题)

大家好。 我知道这个问题已经被问到了,但是Objective-C中的内存pipe理我还没有清晰的描述。 我觉得我有一个很好的把握,但我仍然喜欢以下代码的一些正确的答案。 我有一系列的例子,我希望有人澄清。

为实例variables设置一个值

说我有一个NSMutableArrayvariables。 在我的课上,当我初始化它,我需要调用一个retain吗?

我可以吗?

 fooArray = [[[NSMutableArray alloc] init] retain]; 

要么

 fooArray = [[NSMutableArray alloc] init]; 

是否[[NSMutableArray alloc] init]已经将retain计数设置为1,所以我不需要调用retain ? 另一方面,如果我调用一个我知道的方法返回一个autorelease对象,我肯定会调用retain ,对吧? 像这样:

 fooString = [[NSString stringWithFormat:@"%d items", someInt] retain]; 

属性

我问retain因为我有点困惑如何@property的自动设置工程。

如果我将fooArray设置为带有retain集的@property fooArray ,Objective-C将自动创build下面的setter,对吗?

 - (void)setFooArray:(NSMutableArray *)anArray { [fooArray release]; fooArray = [anArray retain]; } 

所以,如果我有这样的代码: self.fooArray = [[NSMutableArray alloc] init]; (我相信是有效的代码),Objective-C创build一个setter方法,调用retain在分配给fooArray的值上。 在这种情况下, retain计数实际上是2吗?

正确设置属性值的方法

我知道有这个问题和(可能)辩论,但这是正确的方式来设置@property

这个?

 self.fooArray = [[NSMutableArray alloc] init]; 

或这个?

 NSMutableArray *anArray = [[NSMutableArray alloc] init]; self.fooArray = anArray; [anArray release]; 

我希望对这些例子进行一些澄清。 谢谢!

理想情况下,只要有可能,就要使用访问器,尤其是在处理对象时,可以避免许多内存问题。 所以即使对于实例variables,你也应该这样做:

 self.fooArray = ...; 

代替

 fooArray = ...; 

你应该为对象实例variables声明属性的原因是因为内存pipe理稍微复杂一些,每次手动重新创build都是棘手的。 非primefaces保留属性的正确设置方法如下所示:

 - (void)setFoo:(NSArray *)aFoo { if (foo == aFoo) { return; } NSArray *oldFoo = foo; foo = [aFoo retain]; [oldFoo release]; } 

当你做这样的事情(假设foo被保留)的时候,你对保留数为2的实例variables是正确的:

 self.foo = [[NSMutableArray alloc] init]; 

第一个保留计数来自alloc ,第二个来自合成二叉树。 任何这些应该工作:

 // longer, explicit version, releases immediately (more efficient) NSMutableArray *aFoo = [[NSMutableArray alloc] init]; self.foo = aFoo; [aFoo release]; // autoreleased, not so bad unless you're a memory management freak self.foo = [[[NSMutableArray alloc] init] autorelease]; // an even shorter version of the above self.foo = [NSMutableArray array]; 

要创build私有属性,可以在.m实现文件中声明它们作为类扩展。 举一个例子,考虑一个简单的Person对象,它有一个名字和一个布尔属性didSave ,它只是表示对象是否被保存到某个数据库。 既然我们不想把这个暴露给外部世界,但是在实现文件中仍然保留属性的好处,我们可以创build头文件将所有的实例variables(public,private,protected)和公共属性:

 // Person.h @interface Person { NSString *name; @private BOOL didSave; } @property (nonatomic, retain) NSString *name; @end 

但是在实现中声明私有属性:

 // Person.m // property is declared as a class extension, making it // invisible to the outside world. @interface Person () @property BOOL didSave; @end @implementation // synthesize as normal @synthesize name, didSave; @end 

根据苹果的对象所有权政策 ,任何以“ alloc或“ new ,或者包含copy都是由调用者拥有的。

要获得对象的所有权,您必须retain它。

所以,在你的第一个例子中, retain是不必要的,因为你已经拥有这个对象。

正确的方法来做到这一点:

 fooArray = [[NSMutableArray alloc] init]; 

由于autoreleased对象属于当前的自动释放池,所以你必须调用retain来获得它们的所有权,所以这个例子是正确的:

 fooString = [[NSString stringWithFormat:@"%d items", someInt] retain]; 

这也可以很好地工作:

 self.fooString = [NSString stringWithFormat:@"%d items", someInt]; //retained by property setter 

对于使用属性设置器的最后一个示例,这将是正确的方法:

 NSMutableArray *anArray = [[NSMutableArray alloc] init]; self.fooArray = anArray; [anArray release]; 

而不是必须做到上述,我会build议以下解决scheme:

 self.fooArray = [NSMutableArray arrayWithCapacity:10]; 

arrayWithCapacity:将返回一个自动释放的NSMutableArray ,这是属性setter方法的retain 。 🙂

首先,用这一行:

 fooArray = [[NSMutableArray alloc] init]; 

fooArray将自动具有1的保留计数。

其次,是的,它是2.你猜测的实现是正确的。

第三,后者是对的