Где/если освобождать свойства в UITableViewCell

РЕДАКТИРОВАТЬ: Итак, я понял, как решить мою первоначальную проблему, но я не уверен, что это лучший способ.

Мой новый вопрос: скажем, у меня есть подкласс UITableViewCell со следующим объявлением свойства в заголовке:

@property (nonatomic, retain) IBOutlet UILabel *levelLabel;

Это связано в ИБ. Можно ли не выпускать это в Dealloc и вообще не выпускать? Это единственный способ заставить его работать, не выдавая ошибку exc_bad_access. Раньше он вызывал Dealloc, когда tableviewcell исчезал с экрана, но тогда он все еще нуждался в нем. где я могу выпускать материал, или он позаботится об этом за меня?

Оригинальное название: Утечка памяти в UITableView и exc_bad_access Хорошо, я запутался. Я следил за этим онлайн-учебником, создавая собственные UITableViewCells. Я сделал один, и я сделал все, как сказал мне учебник. Мой подкласс UITableViewCell содержит 3 UILabels и 3 UIButtons, и все они определены как свойства и связаны в IB. Мне нужно, чтобы они были доступны для класса, потому что мне нужно знать, когда нажаты кнопки, и иметь возможность изменить текст. Когда я запускаю приложение, я начинаю прокручивать, и через несколько секунд оно вылетает с ex_bad_access в main (нет вывода в консоли). Но когда я запускаю приложение в инструментах с NSZombieEnabled, оно вообще не падает и работает нормально. Однако, поскольку инструменты показывают вам распределения, я вижу, как они растут очень быстро, особенно при прокрутке. Я не знаю, все ли это выделения, или они высвобождаются, но все же это кажется слишком быстрым.

Вот PointCoordinatesCell.h (моя пользовательская ячейка):

#import <UIKit/UIKit.h>

@interface PointCoordinatesCell : UITableViewCell


@property (nonatomic, retain) IBOutlet UILabel *levelLabelLabel;
@property (nonatomic, retain) IBOutlet UILabel *levelLabel;
@property (nonatomic, retain) IBOutlet UILabel *levelDescriptionLabel;
@property (nonatomic, retain) IBOutlet UIButton *beginningButton;
@property (nonatomic, retain) IBOutlet UIButton *developingButton;
@property (nonatomic, retain) IBOutlet UIButton *secureButton;

@end

PointCoordinatesCell.m:

#import "PointCoordinatesCell.h"

@implementation PointCoordinatesCell
@synthesize levelLabel, levelLabelLabel, levelDescriptionLabel, beginningButton, developingButton, secureButton;

- (void)dealloc{
    [super dealloc];
    [levelLabel release];
    [levelLabelLabel release];
    [levelDescriptionLabel release];
    [beginningButton release];
    [developingButton release];
    [secureButton release];
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

В RootViewController.h нет ничего, кроме объявления класса и стандартного импорта. Не определены переменные или методы. Он является подклассом UITableViewController.

RootViewController.m:

#import "RootViewController.h"
#import "StatesAppDelegate.h"
#import "PointCoordinatesCell.h"

@implementation RootViewController

- (void)viewDidLoad {
    [super viewDidLoad];


    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

#pragma mark Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 50;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    return 293;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"PointCoordinatesCell";

    PointCoordinatesCell *cell = (PointCoordinatesCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {

        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"PointCoordinatesCell" owner:self options:nil];

        for (id currentObject in topLevelObjects){
            if ([currentObject isKindOfClass:[UITableViewCell class]]){
                cell =  (PointCoordinatesCell *) currentObject;
                break;
            }
        }
    }

    //cell.capitalLabel.text = [capitals objectAtIndex:indexPath.row];
    //cell.stateLabel.text = [states objectAtIndex:indexPath.row];

    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
    // [self.navigationController pushViewController:anotherViewController];
    // [anotherViewController release];
}



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


@end

person Josh Sherick    schedule 28.08.2011    source источник


Ответы (2)


Кажется, вы делаете какой-то сложный кастинг в своем методе cellForRowAtIndexPath. Я не думаю, что это необходимо. Мне не кажется логичным проверять объект класса UITableViewCell, а затем забрасывать его в пользовательскую ячейку. Ячейка в вашем наконечнике уже должна быть пользовательской ячейкой.

В образце Apple загрузка ячейки намного проще. Вы связываете свою пользовательскую ячейку с IBOutlet в контроллере представления, а затем делаете следующее:

CustomCell *cell = (CustomCell *) [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = customTableViewCell;
    self.customTableViewCell = nil;
    // etc.
}
person Mundi    schedule 28.08.2011

Нет, нельзя не выпускать лейбл. Вы объявили свойство с помощью спецификатора 'retain'. Это означает, что вам придется освободить его, по крайней мере, в Dealloc (безопасный способ сделать это: self. levelLabel = nil;).

Как вы заметили, потребление памяти увеличится во время прокрутки, если вы не освободите объекты (утечки памяти!).

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

person Felix    schedule 28.08.2011