开发者

Memory leak with returned NSMutableArray from function

开发者 https://www.devze.com 2023-01-27 06:04 出处:网络
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.

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.

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 *dat开发者_如何学JAVAabase;
 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;

}

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

In the UIViewController of this class:

in the .h file is declared:

NSMutableArray *loadedInfo;//will contain all query results

@property (nonatomic, retain) NSMutableArray *loadedInfo;

in implementation file .m

@synthesize loadedInfo;

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

//do other initializations

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
}

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;

}

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];
}

Caller Class

in header declare an array

NSMutableArray *theArray;

in init function initialize the array

theArray = [[NSMutableArray alloc] init];

in fill function fill the array with returned array

theArray = [myclass function_A];

in diferent functions use this returned array

in dealloc function release the array.

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

Any help will be apreciated.


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

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.

Don't forget to release in dealloc.

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

0

精彩评论

暂无评论...
验证码 换一张
取 消