2011-03-17 77 views
0

嘿,我只是试图让事情100%清楚在我的脑海,关于iPhone的内存管理,我很确定我有一个很好的理解,虽然我不是100 %自信。了解@property内存管理

让我们创建一个实例属性,它是一个的NSArray:

@interface ExampleAppDelegate : NSObject { 
    NSArray *myArray; 
} 

@property (nonatomic,retain) NSArray *myArray; 

然后合成属性,以便我们可以使用getter和setter方法:

@synthesize myArray; 

现在,这里是我得到稍微困惑..说我们在外部类创建一个数组,并将其分配给我们的代表myArray:

appDelegate = (ExampleAppDelegate *)[[UIApplication sharedApplication] delegate]; 

NSArray *exampleArray = [[NSArray alloc] init]; 
appDelegate.myArray = exampleArray; 
[exampleArray release]; 

现在我们已经为myArray分配了一个保留计数为1,因为它已经占用了分配的exampleArray,因为这样我们将需要在委托dealloc内部调用release来让myArray在代理被销毁时不泄漏:

-(void)dealloc { 
    [super dealloc]; 
    [myArray release]; 
} 

虽然如果我是分配myArray的,像这样:

appDelegate = (ExampleAppDelegate *)[[UIApplication sharedApplication] delegate]; 
NSArray *exampleArray = [NSArray arrayWithObject:[NSString stringWithFormat:@"Hello world"]]; 
appDelegate.myArray = exampleArray; 

我就不是必需的,因为内存管理是为我处理,这样做会在释放分配给myArray的对象调用[myArray release];中的dealloc ?

+3

''[super dealloc]''应该是你的''dealloc''方法中的最后一个。 XCode很可能会抱怨,如果它不是最后一个。 – 2011-03-17 16:33:02

+0

感谢您的指点,我一直认为这是无关紧要的 – Alex 2011-03-17 16:57:13

回答

1

你必须在两种情况下发布myArraymyArray由您的班级“拥有”,因此如果不再需要myArray,则负责减少参考计数。分配给myArray的数组的分配方式无关紧要;每当你进行赋值时,合成的setter函数将增加数组的保留计数(因为你这样指定),所以你的类拥有对数组的引用,你必须在析构函数中补偿它。

如果您已经使用了(nonatomic, copy),则同样适用 - 在这种情况下,您的类将分配数组的副本,因此它也拥有该副本。

假如你使用(nonatomic, assign),你将不会拥有myArray,但在这种情况下,你永远无法确定该阵列仍然存在,当你试图使用它 - 它可能发生,你的程序的其他部分有已经发布了该阵列,并在此期间被释放。因此,对于Objective C对象,除了具有普通旧C类型的属性(例如NSInteger,这只是C中的整数数据类型之一的typedef)外,您不应在属性规范中使用assign

+0

我看到我看到了,这对我来说已经解决了,谢谢,所以我们假设我一直在接收EXC_BAD_ACCESS,这很可能是因为我在一个属性上多次调用发布,或者因为我已经发布了它,然后尝试稍后它已经发布时参考它? – Alex 2011-03-17 16:47:03

+0

@Alex:无论哪种方式,你都释放了太多次。 :-D – kubi 2011-03-17 16:57:37

2

您仍然必须发布myArray。我没有看到在第一个任务和第二个任务之间保留行为的任何区别,只有exampleArray的创建发生了变化。

在第一次分配中,您确实创建了一个未自动释放的实例,在将其分配给您的属性后,其保留计数为2。在那一步之后,您发布了一次,因此保留计数降至其中一个实例。

第二个赋值会导致保留计数为2,在应用程序的下一个运行循环周期后自动降至1,原因是NSArray arrayWithObject确实会返回一个自动释放的实例,如果您喜欢将来使用它。

+1

对。关键在于,如果你的综合setter使用'retain'选项,你的'dealloc'需要调用'release'。 – 2011-03-17 16:28:01

+0

噢好吧,我推测是因为在第二个示例中没有使用alloc init创建exampleArray,因此不需要在对象上调用发布? – Alex 2011-03-17 16:30:16

+0

希望我能接受你的答案,谢谢你的见解! – Alex 2011-03-17 16:57:35