Obj-C, Потенциальная утечка объекта, размещенного на линии, UIBarButtonItem alloc - PullRequest
2 голосов
/ 11 ноября 2011

Я получаю утечку из анализатора, однако это тот же код, который я использую в другом месте без проблем. Я знаю, что использую alloc, и поэтому я должен выпустить, но я делаю это в dealloc.

Что я делаю не так?

Заголовочный файл:

@interface myViewController : UIViewController <UITableViewDataSource, 
               UITableViewDelegate> {

    UIBarButtonItem *addButton;
}
@property (nonatomic, retain) UIBarButtonItem *addButton;

Основной файл:

@synthesize addButton;
- (void)viewDidLoad {

    NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:3];


    addButton = [[UIBarButtonItem alloc]
                            initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                            target:self action:@selector(btnNavAddPressed:)];
    addButton.style = UIBarButtonItemStyleBordered;
    [buttons addObject:addButton];

    [tools setItems:buttons animated:NO];
    [buttons release];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] 
                                initWithCustomView:tools];

    addButton.enabled = FALSE;

- (void)dealloc {
    [addButton release];

Ответы [ 4 ]

2 голосов
/ 11 ноября 2011

когда вы используете свойство и присваиваете ему заданные атрибуты, определяют, увеличивается ли retainCount, если вы присваиваете свойству.В вашем случае вы указали «retain», что означает, что функция setter, которая обрабатывает присвоение вашему свойству, автоматически увеличивает счет сохранения для объекта.

Однако, когда вы пишете

 addButton = [[UIBarButtonItem alloc]
                            initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                            target:self action:@selector(btnNavAddPressed:)];

вы создаете объект с уже сохраненным счетчиком == 1, поэтому при назначении у него будет сохраняться счетчик 2. Правильный способ сделать это - создать временную переменную и создать объект, а затем назначить временную переменную свойствувыпуская темп.переменная:

UIBarButtonItem* tmp = [[UIBarButtonItem alloc]
                            initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                            target:self action:@selector(btnNavAddPressed:)];
self.addButton = tmp;
[tmp release];

конечно, я бы рекомендовал более описательное имя, чем 'temp' в качестве имени переменной.

2 голосов
/ 11 ноября 2011

Вы не используете сеттер, код должен быть:

self.addButton = [[[UIBarButtonItem alloc]
                        initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                        target:self action:@selector(btnNavAddPressed:)] autorelease];

Этого типа проблем можно избежать, используя ивар, имя которого отличается от имени свойства. Это достигается с помощью оператора @synthesize:

@synthesize addButton = _addButton;

Таким образом, любое пропуск self приведет к сообщению об ошибке.

Вот полная реализация (за исключением tools не определено), свойство addButton обрабатывает во всех местах:

@interface myViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
}
@property (nonatomic, retain) UIBarButtonItem *addButton;
@end

@implementation myViewController
@synthesize addButton = _addButton;

- (void)viewDidLoad {
    NSMutableArray* buttons = [NSMutableArray array];

    self.addButton = [[UIBarButtonItem alloc]
                 initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                 target:self action:@selector(btnNavAddPressed:)];
    self.addButton.style = UIBarButtonItemStyleBordered;
    [buttons addObject:self.addButton];

    [tools setItems:buttons animated:NO];

    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:tools] autorelease];

    self.addButton.enabled = FALSE;
}
- (void)dealloc {
    [_addButton release];
}
@end
1 голос
/ 11 ноября 2011

Оба приведенных выше ответа вводят в заблуждение. Вам не нужно использовать сеттер, совершенно нормально назначать объекты непосредственно iVars. Вы должны освободить все, что вы распределяете или сохраняете. Проблема у вас здесь:

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];

Эта строка выделяет экземпляр UIBarButtonItem и устанавливает для него свойство rightBarButtonItem navigationItem. Это означает, что navigationItem сохраняет UIBarButtonItem и несет ответственность за это. Вы несете ответственность за выпуск этого б / к alloc, а вы - нет. Измените код на это:

self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:tools] autorelease];

и эта утечка исчезла.

0 голосов
/ 11 ноября 2011

Вы не пользуетесь объявленной собственностью, но я не вижу проблем с addButton. Утечка кажется больше в:

self.navigationItem.rightBarButtonItem = 
                             [[UIBarButtonItem alloc] initWithCustomView:tools];

Просто добавьте autorelease и утечка исчезнет.

...