Утечка памяти при возврате NSMutableArray из функции - PullRequest
0 голосов
/ 24 ноября 2010

У меня проблемы с реализацией управления памятью цели 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

В другом методе загружаемый файл заполняется результатами запроса:

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

}

Я прочитал руководство по программированию управления памятью и несколько постов, где объясняются правила.Хорошо, если я следую правилам (когда объект должен быть возвращен из метода, это должно быть объявлено с помощью автоматического выпуска), приложение вылетает, но если я этого не делаю, память приложения занимает более 30 МБ!

Моя цель - создать функцию, в которой

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

/fill the array

return [theArray autorelease];
}

Класс вызывающего абонента

в заголовке объявляет массив

NSMutableArray *theArray;

в функции инициализации инициализирует массив

theArray = [[NSMutableArray alloc] init];

в функции заполнения заполнить массив возвращаемым массивом

theArray = [myclass function_A];

в различных функциях использовать этот возвращенный массив

, в функции dealloc освободить массив.

Возможно ли это?Как лучше всего это реализовать?

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 24 ноября 2010

Похоже, что в своем классе вызывающего вы забыли release старый theArray объект, и вам следует retain его.

Проще всего было бы объявить theArray в классе вызывающего как retain ed свойство (или скопировать), а при настройке использовать предоставленный установщик:

self.theArray = [myclass function_A]; 

, который вызовет правильное поведение управления памятью.

Не забудьте release в dealloc.

Возврат автоматически выпущенного объекта - это нормально, и чего следует ожидать с этим именем метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...