Когда я должен освободить мой массив? - PullRequest
8 голосов
/ 24 июня 2011

Я анализирую некоторые JSON из Интернета, а затем добавляю их в массив, который является источником данных для моего UITableView.Я не уверен, когда мне следует освобождать мой массив?

.h: items

@property(nonatomic,retain)NSMutableArray*  items;

.m: connectionDidFinishLoading

// fetch succeeded    
    NSString* json_string = [[NSString alloc] initWithData:retrievedData encoding:NSUTF8StringEncoding];

    //Check ST status
    int status =  [[[[json_string objectFromJSONString] valueForKey:@"response"] valueForKey:@"status"]intValue];
    //NSLog(@"Status: %d", status);

    items = [[NSMutableArray alloc] init];
    NSDictionary* messages = [[NSDictionary alloc] init]; 

    switch (status) {
        case 200:
            messages = [[[json_string objectFromJSONString] valueForKey:@"messages"] valueForKey:@"message"];

            for (NSDictionary *message in messages)
            {
                [items addObject:message];
            }
            [self.tableView reloadData];
        break;

        default:
        break;
    }

Ответы [ 7 ]

9 голосов
/ 24 июня 2011

Во-первых, вы можете объявить items как экземпляр NSMutableArray, если вы намереваетесь вызвать addObject: для него.

Два, объявите его как свойство, чтобы, если вы получите его несколько раз, старое значение будет выпущено, когда вы это сделаете.

self.items = [NSMutableArray array];

И правильная точка его освобождения будетбыть dealloc.

2 голосов
/ 29 июня 2011

Выпуск в неправильных местах иногда приводит к утечкам памяти, прежде чем само выделение у вас может возникнуть условие вроде if () {[... release]}. Не тестировалось, но этот тип выпуска избегает утечек.

2 голосов
/ 28 июня 2011

Возможно, вы не захотите немедленно выпустить его, если вы:

  • использовать didSelectRowAtIndexPath: метод для подробных видов и передавать им эти данные
  • определение пользовательских стилей UITableViewCell в cellForRowAtIndexPath: метод
  • использовать эти данные в другом месте

Рекомендуется объявлять переменную экземпляра и синтезировать ее в .m, использовать в соответствующих операциях и выпускать в методе dealloc.

Одна из возможных точек выпуска, которую вы можете использовать, - это когда вы обновляете данные, показанные в таблице.

Пример:

Я получаю словари в массиве из API в моем приложении и использую что-то подобное.

MyTableViewController.h

@interface MyTableViewController {
    NSMutableArray *items;
}

@property (nonatomic, retain) NSMutableArray *items;

@end

MyTableViewController.m

@implementation MyTableViewController

@synthesize items;

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [items count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellIdentifier = @"FilesCellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }

    cell.textLabel.text = [[items objectAtIndex:indexPath.row] valueForKey:@"name"];
    cell.imageView.image = [UIImage imageNamed:[[NSString alloc] initWithFormat:@"filetype_%@.png", [[items objectAtIndex:indexPath.row] valueForKey:@"type"]]];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
        MyDetailViewController *detailViewController = [[MyDetailViewController alloc] initWithNibName:@"MyDetailViewController" bundle:[NSBundle mainBundle]];
        detailViewController.item = [items objectAtIndex:indexPath.row];
        [self.navigationController pushViewController:detailViewController animated:YES];
        [detailViewController release];
        detailViewController = nil;
    }
}

- (void)getItems
{
    [items release];
    items = [[NSMutableArray alloc] init];

    //Do some requests here

    for (NSDictionary *dict in results)
    {
        [items insertObject:dict atIndex:0];
    }

    [self.tableView reloadData];
    [self stopLoading];
}

@end
0 голосов
/ 02 июля 2011

В соответствии с документацией Apple о методе UITableView reloadData :

"[...] Для эффективности табличное представление повторно отображает только те строки, которые видны"

Это означает, что вы не должны освобождать массив элементов, пока таблица используется, то есть вы должны объявить массив как свойство.

Сначала, потому что если вы прокручиваете представление, выпо-прежнему потребуется информация items для отображения строк ниже или выше.

И во-вторых, поскольку, будучи свойством, вы гарантируете, что предыдущее значение будет выпущено, если вам случится присвоить новое значениеitems.

Наконец, обычное место для освобождения свойства - метод dealloc и в зависимости от вашей реализации в методе viewDidUnload.

0 голосов
/ 28 июня 2011

Надлежащим способом является сделать его свойством в классе .h, поскольку вы объявили его как свойство: помните, что одна вещь всегда выделяет свойство с помощью self.

ваше заявление items=[[NSMutableArray alloc] init];

неверно. (Используйте self) также, поскольку ваше свойство retain, введите использование alloc для него, увеличьте количество сохраняемых записей. Это даст вам утечку.

, поэтому используйте таким образом в viewDidLoad

NSMutableArray *tempArray=[[NSMutableArray alloc] init];
self.items=tempArray;
[tempArray release];

затем освободите ваш массив элементов в dealloc и установите его равным nil в viewDidUnload

- (void)viewDidUnload {
    [super viewDidUnload];
    self.items=nil;
}

- (void)dealloc {
    [self.items release];
[super dealloc];
}

Надеюсь, теперь вы понимаете, как вы должны это использовать.

0 голосов
/ 24 июня 2011

Понятно, что ваш массив item будет использоваться UITableView для отображения данных.

Сначала объявите его как переменную экземпляра в вашем классе .h.

.h класс

@interface MyClass 
{
  MSMutableArray* items;
}
@property(nonatomic,retain) MSMutableArray* items;

@end

В вашем .m классе.

@synthesis iMyArray;

И ваш код для заполнения массива должен быть

NSMutabelArray* itemsTemp = [[NSMutabelArray alloc] initWithCapacity:1];

messages = [[[json_string objectFromJSONString] valueForKey:@"messages"] valueForKey:@"message"];
[json_string release];

for (NSDictionary *message in messages) {
    NSLog(@"%@",[message valueForKey:@"body"]);
    [itemsTemp addObject:message];
}


self.items= itemsTemp;

[itemsTemp release];
itemsTemp = nil;

[self.tableView reloadData];

Теперь в dealloc освободите ваш экземпляр массива.

-(void) dealloc
{
   if(items )
   {
    [items release];
    items = nil ;
   }
   [super dealloc];
}
0 голосов
/ 24 июня 2011

Наиболее распространенным является использование переменной items в качестве атрибута вашего класса, если вам, вероятно, понадобится использовать его в вашем методе tableView:cellForRowAtIndexPath:.

Итак, имея его в качестве переменной атрибута, вы можете освободить его по методу dealloc.

...