Программирование табличного представления - PullRequest
0 голосов
/ 03 февраля 2010

Почему я не могу добавить подпредставление в представление содержимого ячейки табличного представления?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellTableIdentifier = @"CellTableIdentifier ";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellTableIdentifier];
    if (cell == nil) 
    {
        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellTableIdentifier];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, 70, 15)];
        label.text=@"Name:";
        [cell.contentView addSubview:label];
    }
    return [cell autorelease];

}

1 Ответ

3 голосов
/ 03 февраля 2010

Это должна быть проблема управления памятью.

Рассмотрим это утверждение:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellTableIdentifier];

Согласно правилу управления памятью Какао , это не метод alloc / new / copy, т.е. вы не владеете cell, поэтому вам следует не -release после окончания использования. Однако следующее утверждение (предположим cell != nil):

return [cell autorelease];

заставит cell быть выпущенным (некоторое время спустя), вызывая двойное освобождение ячейки (некоторое время спустя). Поэтому вы должны просто return cell;.

А что если cell == nil? Внутри ветки if вы написали

    cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellTableIdentifier];

Поскольку cell создается с alloc, вы несете ответственность за -release. Но так как вы собираетесь вернуть его другим, вы должны отказаться от права собственности, не допуская немедленного освобождения. Именно здесь используется -autorelease, чтобы временно передать владение «пулу авто-релиза», чтобы у другого кода была возможность вернуть владение (-retain оно) до того, как оно было сброшено в пустоту.

Другими словами, вы должны заменить это утверждение на cell = [[[...] autorelease];.

Точно так же вы должны -release * label, потому что он -alloc -ед, и вы больше не являетесь его владельцем. Однако вам не нужно -autorelease, потому что вы уверены, что уже есть другой владелец (cell.contentView).

Подводя итог, вы должны переписать код как:

 static NSString *CellTableIdentifier = @"CellTableIdentifier ";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellTableIdentifier];
if (cell == nil) 
{
    cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellTableIdentifier] autorelease];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, 70, 15)];
    label.text=@"Name:";
    [cell.contentView addSubview:label];
    [label release];
}
return cell;

Кстати, вы можете использовать UITableViewCellStyleValue2 (например, адресную книгу), чтобы избежать путаницы с иерархией представления.

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