如何在iPhone中释放已声明对象的内存[duplicate]

时间:2022-10-08 17:21:25

This question already has an answer here:

这个问题已经有了答案:

I'm facing small problem,

我面对小问题,

I declare an array in .h file and allocate it in viewDodLoad method. In dealloc method I check if array not equal to nil then array=nil. But it's crashing in iOS 5.1.1. I can't understand reason for this crash.

我在.h文件中声明一个数组并在viewDodLoad方法中分配它。在dealloc方法中,我检查数组是否不等于nil,那么array=nil。但它在iOS 5.1.1中崩溃了。我不明白这次事故的原因。

My code,

我的代码,

   @interface SampleApp : UIViewController
   {
        NSMutableArray *objArray;
   }
   @end

   @implementation SampleApp

   - (void)viewDidLoad
   {
        [super viewDidLoad]; 
        objArray=[[NSMutableArray alloc]init];
   }
   -(void)dealloc
   {
      [super dealloc];
      if (objArray!=nil)
     {
         [objArray removeAllObjects];
         [objArray release];objArray=nil;
     }
  }

3 个解决方案

#1


3  

Add [super dealloc]; at the end of dealloc method and not at beginning. It is recommended by Apple in its documentation for dealloc method.

添加(超级dealloc);在dealloc方法的末尾而不是开始。在dealloc方法的文档中,苹果推荐了它。

When not using ARC, your implementation of dealloc must invoke the superclass’s implementation as its last instruction.

当不使用ARC时,您的dealloc实现必须调用超类的实现作为它的最后一条指令。

Modify your code as below,

修改您的代码如下,

   -(void)dealloc
   {
      if (objArray!=nil)
     {
         [objArray removeAllObjects];
         [objArray release];objArray=nil;
     }
      [super dealloc];
   }

Also, you need not call [objArray removeAllObjects] when you are releasing the entire array. When array is released, internally it will call release on all contained objects.

此外,在释放整个数组时,不需要调用[objArray removeAllObjects]。当数组被释放时,内部它将调用所有包含对象的释放。

Hope that helps!

希望会有帮助!

#2


1  

[super dealloc] method must be call in end of this method. Because you can not access variables of the superclass anymore because they are released when you call [super dealloc]. It is always safe to call the superclass in the last line.

方法的末尾必须调用[super dealloc]方法。因为您不能再访问超类的变量,因为它们在调用[super dealloc]时被释放。在最后一行调用超类总是安全的。

-(void)dealloc
   {

// ----------- your stuff ------------

      [super dealloc];

  }

#3


0  

With manual memory management, your -dealloc method looks as follows:

使用手动内存管理,您的-dealloc方法如下:

-(void)dealloc
{
    [objArray release];   // objArray *may* be nil, and this is 
                          // sufficient to release all elements as well.

    // call super at the end  
    [super dealloc];
}

Additionally, you have a potential memory leak in your method -viewDidLoad. If you do it like your example:

另外,在方法-viewDidLoad中有一个潜在的内存泄漏。如果你像你的例子一样:

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    objArray=[[NSMutableArray alloc]init];
}

you may assign objArray a new pointer even if objArray already holds a valid object. The new pointer value will simply override the old, and thus you cannot release the old anymore.

即使objArray已经持有一个有效的对象,也可以给objArray分配一个新的指针。新的指针值将简单地覆盖旧的,因此您不能再释放旧的。

One way is to check whether objArray is not nil and then release it before assigning it a new value:

一种方法是检查objArray是否不是nil,然后在给它赋一个新值之前释放它:

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    if (objArray) {
        [objArray release], objArray = nil;
    }
    objArray = [[NSMutableArray alloc]init];
}

The better approach however is to employ "lazy initializing properties":

然而,更好的方法是采用“惰性初始化属性”:

First, define an "internal property" for your array (unless you want the array publicly accessible). In your .m file:

首先,为您的数组定义一个“内部属性”(除非您想让数组公开访问)。在你的m文件:

// In your implementation file define a private property in a class extension:   
@interface SampleApp ()
@property (nonatomic) NSMutableArray* objArray;       
@end


@implementation SampleApp

@synthesize objArray = _objArray;   // this will create the setter

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

// Lazy init property:   (this is the getter)
- (NSMutableArray*) objArray {
    if (_objArray == nil) {
        _objArray = [[NSMutableArray alloc] init];
    }
    return _objArray;
}

- (void) viewDidLoad {
    [super viewDidLoad]; 

    // When needing the array, simply *and always* access it 
    // through the property "self.objArray":
    NSUInteger count = [self.objArray count];
}

...

Lazy initialization of properties are quite handy. Basically, you won't worry anymore if they are initialized or not - they simply are, when you use the property accessor.

属性的惰性初始化非常方便。基本上,如果它们初始化了或者没有初始化,您就不会再担心了——当您使用属性访问器时,它们只是初始化了。

#1


3  

Add [super dealloc]; at the end of dealloc method and not at beginning. It is recommended by Apple in its documentation for dealloc method.

添加(超级dealloc);在dealloc方法的末尾而不是开始。在dealloc方法的文档中,苹果推荐了它。

When not using ARC, your implementation of dealloc must invoke the superclass’s implementation as its last instruction.

当不使用ARC时,您的dealloc实现必须调用超类的实现作为它的最后一条指令。

Modify your code as below,

修改您的代码如下,

   -(void)dealloc
   {
      if (objArray!=nil)
     {
         [objArray removeAllObjects];
         [objArray release];objArray=nil;
     }
      [super dealloc];
   }

Also, you need not call [objArray removeAllObjects] when you are releasing the entire array. When array is released, internally it will call release on all contained objects.

此外,在释放整个数组时,不需要调用[objArray removeAllObjects]。当数组被释放时,内部它将调用所有包含对象的释放。

Hope that helps!

希望会有帮助!

#2


1  

[super dealloc] method must be call in end of this method. Because you can not access variables of the superclass anymore because they are released when you call [super dealloc]. It is always safe to call the superclass in the last line.

方法的末尾必须调用[super dealloc]方法。因为您不能再访问超类的变量,因为它们在调用[super dealloc]时被释放。在最后一行调用超类总是安全的。

-(void)dealloc
   {

// ----------- your stuff ------------

      [super dealloc];

  }

#3


0  

With manual memory management, your -dealloc method looks as follows:

使用手动内存管理,您的-dealloc方法如下:

-(void)dealloc
{
    [objArray release];   // objArray *may* be nil, and this is 
                          // sufficient to release all elements as well.

    // call super at the end  
    [super dealloc];
}

Additionally, you have a potential memory leak in your method -viewDidLoad. If you do it like your example:

另外,在方法-viewDidLoad中有一个潜在的内存泄漏。如果你像你的例子一样:

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    objArray=[[NSMutableArray alloc]init];
}

you may assign objArray a new pointer even if objArray already holds a valid object. The new pointer value will simply override the old, and thus you cannot release the old anymore.

即使objArray已经持有一个有效的对象,也可以给objArray分配一个新的指针。新的指针值将简单地覆盖旧的,因此您不能再释放旧的。

One way is to check whether objArray is not nil and then release it before assigning it a new value:

一种方法是检查objArray是否不是nil,然后在给它赋一个新值之前释放它:

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    if (objArray) {
        [objArray release], objArray = nil;
    }
    objArray = [[NSMutableArray alloc]init];
}

The better approach however is to employ "lazy initializing properties":

然而,更好的方法是采用“惰性初始化属性”:

First, define an "internal property" for your array (unless you want the array publicly accessible). In your .m file:

首先,为您的数组定义一个“内部属性”(除非您想让数组公开访问)。在你的m文件:

// In your implementation file define a private property in a class extension:   
@interface SampleApp ()
@property (nonatomic) NSMutableArray* objArray;       
@end


@implementation SampleApp

@synthesize objArray = _objArray;   // this will create the setter

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

// Lazy init property:   (this is the getter)
- (NSMutableArray*) objArray {
    if (_objArray == nil) {
        _objArray = [[NSMutableArray alloc] init];
    }
    return _objArray;
}

- (void) viewDidLoad {
    [super viewDidLoad]; 

    // When needing the array, simply *and always* access it 
    // through the property "self.objArray":
    NSUInteger count = [self.objArray count];
}

...

Lazy initialization of properties are quite handy. Basically, you won't worry anymore if they are initialized or not - they simply are, when you use the property accessor.

属性的惰性初始化非常方便。基本上,如果它们初始化了或者没有初始化,您就不会再担心了——当您使用属性访问器时,它们只是初始化了。