从函数返回的NSMutableArray导致内存泄漏

时间:2010-11-24 11:59:18

标签: objective-c nsmutablearray

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

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

-(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的委托方法的其他类。

在这个类的UIViewController中:

声明:.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用查询结果填充:

-(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的委托和用于创建返回单元格的方法

- (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!

我的目标是创建一个

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

/fill the array

return [theArray autorelease];
}

来电者等级

标头中的

声明一个数组

NSMutableArray *theArray;

在init函数中初始化数组

theArray = [[NSMutableArray alloc] init];
填充函数中的

用返回的数组填充数组

theArray = [myclass function_A];

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

在dealloc函数中释放数组。

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

任何帮助都会被贬低。

1 个答案:

答案 0 :(得分:0)

在您的来电者课程中,您似乎忘记了release旧的theArray对象,并且您应该retain它。

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

self.theArray = [myclass function_A]; 

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

不要忘记release中的dealloc

返回一个自动释放的对象很好,并且应该对该方法名称有所期待。