Objective-C iVars / properties的内存管理技术

时间:2010-06-14 23:51:52

标签: objective-c memory properties

以下代码是否做了不必要的事情?

@interface MyClass {
   NSArray   *myArray;
}

-(void)replaceArray:(NSArray *)newArray;

@implementation MyClass

-(void)replaceArray:(NSArray *)newArray {
   if( myArray )
   {
      [myArray release];
      myArray = nil;
   }

   myArray = [[NSArray alloc] initWithArray: newArray];
}

@end

如果我做了以下更改怎么办:

1)使myArray成为一个属性:

@property (nonatomic, retain) NSArray myArray;

2)将作业更改为:

self.myArray = [NSArray arrayWithArray: newArray];

这会让我删除有条件的吗?

4 个答案:

答案 0 :(得分:3)

你根本不需要条件;您可以发送消息nil(包括release),但不会发生任何事情。您也不需要分配新数组;你可以retain代替传给你的那个。如果您担心实际获得NSMutableArray,可以复制一份。我这样做:

- (void)replaceArray:(NSArray *)newArray
{
    [myArray autorelease];
    myArray = [newArray copy];
}

或者,如果您不想使用autorelease,则可以执行以下操作:

- (void)replaceArray:(NSArray *)newArray
{
    if (myArray != newArray) {
        [myArray release];
        myArray = [newArray copy];
    }
}

答案 1 :(得分:0)

你已经可以摆脱条件了。如果数组是nil,那么你将向nil发送一条消息,这是一个no-op。无论如何,对nil的赋值都是毫无意义的。如果你将它设为retain属性,则显式释放旧值是错误的。

但是,有一种情况是代码无法正常工作:当参数是当前值时。在这种情况下,您将释放当前值,然后尝试使用已释放的对象(可能已经解除分配)来创建新数组。

答案 2 :(得分:0)

对以下内容进行成像:

MyClass * myObj;
// init myObj
NSArray * array = [myObj myArray];
[myObj replaceArray:array];

在这种情况下,myArraynewArray是相同的,这意味着您在发布后正在使用它。要解决此问题,您只需删除replaceArray:方法,然后将该属性实现为@synthesize myArray。所以上面的代码改为

MyClass * myObj;
// init myObj
NSArray * array = [myObj myArray];
[myObj setMyArray:array];

并通过综合实施解决您的问题。

请注意,您是通过创建新数组来设置值:

myArray = [[NSArray alloc] initWithArray: newArray];

如果这是您想要的行为,则应将属性定义更改为复制而不是保留:

@property (nonatomic, copy) NSArray myArray;

答案 3 :(得分:0)

我投了mipadi,因为他的回答是在你问的问题的背景下,但为什么不只是使用一个属性并取消replaceArray:完全:

@interface MyClass {
   NSArray   *myArray;
}

@property (copy) NSArray* myArray;

@end

@implementation MyClass

@synthesize myArray;

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

@end