从函数返回 NSMutableArray 的内存泄漏 [英] Memory leak with returned NSMutableArray from function

查看:42
本文介绍了从函数返回 NSMutableArray 的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在实现目标 c 的内存管理时遇到了问题.我已经阅读了几本手册,但我认为我丢失了一些东西.

I'm having problems with the implementation of the memory management of objective c. I've reed several manuals, but i think that I'm loosing something.

我正在开发一个应用程序,它使用一个加载查询结果的 UITableView;

I'm developing an application that uses a UITableView that is loaded with the results of a query;

-(NSMutableArray *)sqlReader:(NSString *)sqlString
{
 NSMutableArray *sqlResult = [[[NSMutableArray alloc] init] autorelease];
 NSMutableArray *sqlRow = [[NSMutableArray alloc] init];

 sqlite3 *database;
 int dataType;
 int intResult;
 int colCount;
 int a;

 if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
 {
  const char *sqlStatement = [sqlString UTF8String];
  sqlite3_stmt *compiledStatement;
  if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
  {
   [sqlResult removeAllObjects];


   while(sqlite3_step(compiledStatement) == SQLITE_ROW)
   {
    //[sqlRow removeAllObjects];
    sqlRow = [[NSMutableArray alloc] init];
    colCount = sqlite3_data_count(compiledStatement);
    for (a=0;a<colCount;a++)
    {
     dataType = sqlite3_column_type(compiledStatement, a);

     if (dataType == SQLITE_INTEGER)
     {
      intResult = sqlite3_column_int(compiledStatement, a);
      [sqlRow addObject:[NSString stringWithFormat:@"%d",intResult]];
     }
     else if (dataType == SQLITE_TEXT)
     {
      [sqlRow addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, a)]];
     }
     else if (dataType == SQLITE_BLOB)
     {
      NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(compiledStatement, a) length: sqlite3_column_bytes(compiledStatement, a)];           
      [sqlRow addObject:[UIImage imageWithData:dataForCachedImage]];
      [dataForCachedImage release];
     }

    }
    [sqlResult addObject:sqlRow];
    [sqlRow release];
   }
   return sqlResult;
  }
 }
 return nil;

}

包含此函数的类与实现 UITableView 的委托方法的类不同.

The class that contains this function is used from a different class that is where the delegate methods of UITableView are implemented.

在这个类的 UIViewController 中:

In the UIViewController of this class:

在.h文件中声明:

NSMutableArray *loadedInfo;//will contain all query results

@property (nonatomic, retain) NSMutableArray *loadedInfo;

在实现文件 .m

@synthesize loadedInfo;

- (void)viewDidLoad {
 loadedInfo = [[NSMutableArray alloc] init];

//do other initializations

在其他方法中,loadedInfo 填充查询结果:

In other method is where loadedInfo is filled with the query results:

-(void)loadTemas
{
 loadedInfo = [SQL sqlReader:@"SELECT * FROM TEMAS ORDER BY NOMBRETEMA;"];
//This returns an autoreleased NSMutableArray 
 [detail reloadData];
 //This calls the delegate methods of UITableView
}

下面两个方法分别是UITableView的delegate和一个用来创建返回cell的方法

The following two methods are the delegate of UITableView and a method used to create the returned cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
 if (searchMode == 0)
  return [self setTemaCell:indexPath tableView:tableView];
 else if (searchMode == 1)
  return [self setItemCell:indexPath tableView:tableView];

} 
#pragma mark Set Cell Functions
-(UITableViewCell *)setTemaCell:(NSIndexPath *)indexPath tableView:(UITableView *)tableView
{ 
 UITableViewCell *customCell;
 UIImageView *imgIcon;
 UILabel *lblTitle; 

 customCell = [tableView dequeueReusableCellWithIdentifier:@"CellID"];

 CGRect frame = CGRectMake(0, 0, 0, 20);

 //if (!customCell)
 //{
  customCell = [[[UITableViewCell alloc] initWithFrame:frame reuseIdentifier:@"CellID"] autorelease];
 //}

 //customCell = [customCell initWithFrame:frame reuseIdentifier:@"CellID"];

 customCell.selectionStyle = UITableViewCellSelectionStyleNone;

 imgIcon = [[UIImageView alloc] initWithFrame:CGRectMake(10, 13, 64, 64)];

 [imgIcon setImage:[self imageWithImage:[[loadedInfo objectAtIndex:indexPath.row] objectAtIndex:2] scaledToSize:CGSizeMake(64, 64)]];
//This is the line where I'm having an EXEC_BAD_ACCESS.

 [customCell.contentView addSubview:imgIcon];
 [imgIcon release];
 imgIcon = nil;

 lblTitle = [[[UILabel alloc] initWithFrame:CGRectMake(80, 30, 270, 20)] autorelease];
 lblTitle.font = [UIFont systemFontOfSize:24.0];
 lblTitle.textAlignment = UITextAlignmentLeft;
 lblTitle.backgroundColor= [UIColor whiteColor];
 lblTitle.textColor = [UIColor blackColor];
 lblTitle.text = [[loadedInfo objectAtIndex:indexPath.row] objectAtIndex:1];
 [lblTitle setAlpha:1];
 [customCell.contentView addSubview:lblTitle];


 [customCell setAlpha:1];

 return customCell;

}

我已经阅读了内存管理编程指南和一些解释规则的帖子.好吧,如果我遵循规则(当一个对象必须从一个方法返回时,这必须用 autorelease 声明)应用程序崩溃,但如果我不这样做,应用程序内存占用高于 30 MB!

I've readed the Memory Management Programing guide and several posts where explain the rules. Well, if i follow the rules (When an object must be returned from a method, this have to be declared with autorelease) the app crashes but if I don't the app memory occupation is higher than 30 MB!

我的目标是创建一个函数

My target is create a function where

(NSMutableArray *)function_A
{
NSMutableArray *theArray = [[NSMutableArray alloc] init];

/fill the array

return [theArray autorelease];
}

来电类

在头部声明一个数组

NSMutableArray *theArray;

在init函数中初始化数组

in init function initialize the array

theArray = [[NSMutableArray alloc] init];

在fill函数中用返回的数组填充数组

in fill function fill the array with returned array

theArray = [myclass function_A];

在不同的函数中使用这个返回的数组

in diferent functions use this returned array

在 dealloc 函数中释放数组.

in dealloc function release the array.

这可能吗?实现这一点的最佳方法是什么?

Is this possible? How is the best way to implement this?

我们将不胜感激任何帮助.

Any help will be apreciated.

推荐答案

看起来在你的调用者类中你忘记了 release 旧的 theArray 对象,你应该保留它.

It looks like in your caller class you forget to release the old theArray object, and you should retain it.

最简单的方法是在调用者类中将 theArray 声明为 retain ed 属性(或复制),并在设置时使用提供的 setter:

Easiest would be to declare theArray in your caller class as a retained property (or copied), and when setting, use the provided setter:

self.theArray = [myclass function_A]; 

这将调用正确的内存管理行为.

which will invoke the correct memory management behaviour.

不要忘记在deallocrelease.

返回一个自动释放的对象是可以的,并且使用该方法名称应该会得到什么.

Returning an autoreleased object is fine and what one should expect with that method name.

这篇关于从函数返回 NSMutableArray 的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆