#objective-c #xcode #cocoa-touch #analyzer
#objective-c #xcode #cocoa-touch #анализатор
Вопрос:
Я объявил следующую переменную как переменную экземпляра и использую ее в своем m-файле, однако я получаю предупреждение.
TransparentToolbar *tools;
Потенциальная утечка объекта, выделенного в строке…
Например, я пытался создать для него свойство..
@property (nonatomic, retain) TransparentToolbar *tools;
И синтезирую и освобождаю его, но мой просмотр завершается сбоем в конце dealloc.
Что я делаю не так?
ОТРЕДАКТИРУЙТЕ то же предупреждение в pickerSortingDataCurrent …
h
@interface myViewController : UIViewController <UIActionSheetDelegate,
UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDelegate,
UITableViewDataSource, MFMailComposeViewControllerDelegate> {
TransparentToolbar *tools;
NSArray *pickerSortingDataCurrent;
}
@property (nonatomic, retain) TransparentToolbar *tools;
@property (nonatomic, retain) NSArray *pickerSortingDataCurrent;
m
@synthesize pickerSortingDataCurrent;
@synthesize tools;
- (void)viewDidLoad {
[super viewDidLoad];
tools = [[[TransparentToolbar alloc]
initWithFrame:CGRectMake(0, 0, 70, 44.01)] autorelease];
tools.barStyle = UIBarStyleBlackOpaque;
self.pickerSortingDataCurrent = [[NSArray alloc] initWithObjects:
@"Next Date Ascending",
@"Next Date Descending", nil]; // removed some items here
}
- (void)dealloc {
[tools release];
[pickerSortingDataCurrent release];
[super dealloc];
}
Ааааа, у меня автоматический выпуск…. но это не решает проблему pickerSortingDataCurrent …
Редактировать…
#import "TransparentToolbar.h"
@implementation TransparentToolbar
- (void)drawRect:(CGRect)rect {
// do nothing in here
}
- (void) applyTranslucentBackground
{
self.backgroundColor = [UIColor clearColor];
self.opaque = NO;
self.translucent = YES;
}
- (id) init
{
self = [super init];
[self applyTranslucentBackground];
return self;
}
// Override initWithFrame.
- (id) initWithFrame:(CGRect) frame
{
self = [super initWithFrame:frame];
[self applyTranslucentBackground];
return self;
}
@end
ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ
Комментарии:
1. Трудно сказать без кода.
2. Не могли бы вы включить свой
dealloc
код?3. Я получаю ту же проблему с массивом данных интерфейса, который я заполняю в viewDidLoad, см. Редактирование выше.
4. чем больше информации вы предоставляете, тем проще нам вам помочь. например, как использовать вашу собственность? освобождение, определенное в TransparentToolbar и т.д.
5. @Anders K, смотри класс TransparentToolbar выше
Ответ №1:
Если вы определяете @property
, то обычно при каждом обращении к ivar в вашем классе вы используете средство получения / установки, будь то точечная нотация или стандартный вызов метода.
Точечная нотация
id localyMyVar = self.myVar;
self.myVar = @"A string";
Вызов стандартного метода
id localMyVar = [self myVar];
[self setMyVar:@"A string"];
Если вы всегда явно используете эти методы получения и установки, то вам практически не нужно вызывать release где-либо в вашем коде, кроме dealloc
или переопределенного setMyVar:
метода. Выполнение этого таким образом позволяет управлять памятью в ограниченных местах. Если вы начнете освобождать и сохранять себя, то при первом запуске все может быть немного сложнее.
Обновить
@bbum дает вам ответ, но я думаю, что вам также было бы полезно быть более последовательным в вашем кодировании.
Например, перед строкой-нарушителем вы присваиваете значение непосредственно ivar без использования установщика. Будьте последовательны и используйте средство установки / получения, на синтез которого вы потратили время. Я бы переписал
tools = [[[TransparentToolbar alloc]
initWithFrame:CGRectMake(0, 0, 70, 44.01)] autorelease];
tools.barStyle = UIBarStyleBlackOpaque;
Для
TransparentToolbar *tmpTools = [[TransparentToolbar alloc] initWithFrame:CGRectMake(0, 0, 70, 44.01)];
tmpTools.barStyle = UIBarStyleBlackOpaque;
self.tools = tmpTools;
[tmpTools release]; tmpTools = nil;
Ваши init
методы на самом деле не соответствуют рекомендациям, вы также должны проверять, что self
действительно установлено, поэтому это должно выглядеть примерно так:
- (id)init
{
self = [super init];
if (self) {
[self applyTranslucentBackground];
}
return self;
}
Обновить
Утечка памяти, которую вы видите здесь:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];
это потому, что вы просматриваете документы для UINavigationItem, вы увидите, что rightBarButtonItem
он объявлен как retain
@property(nonatomic, retain) UIBarButtonItem *rightBarButtonItem
Следовательно, вызов self.navigationItem.rightBarButtonItem
сохранит 1 для передаваемого вами объекта, а затем вы выделяете / инициализируете, что является еще одним сохранением 1. UINavigationItem
Освободит его сохранение, когда оно будет освобождено, но ваше исходное сохранение все еще будет висеть поблизости.
Исправление:
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
[rightBarButtonItem release]; rightBarButtonItem = nil;
Комментарии:
1. Я все еще получаю предупреждение, вызванное этой строкой
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];
Ответ №2:
self.pickerSortingDataCurrent = [[NSArray alloc] initWithObjects:
@"Next Date Ascending",
@"Next Date Descending", nil]; // removed some items here
1 сохранить количество для alloc, 1 сохранить количество для присвоения retain
@property
.
Перепишите это как:
NSArray *labels = [[NSArray alloc] initWithObjects:
@"Next Date Ascending",
@"Next Date Descending", nil];
self.pickerSortingDataCurrent = labels;
[labels release];
(Или вы могли бы использовать autorelease
)
Комментарии:
1. Это все еще выдает мне предупреждение из строки перед см. Комментарий выше.
Ответ №3:
Если вы создаете свойство с помощью retain
, вы должны установить для него значение nil в вашем методе dealloc.
т. е.
@interface DMFakeyClass : NSObject
@property (nonatomic, retain) NSString *bogusString;
@end
@implementation DMFakeyClass
-(void)dealloc {
self.bogusString = nil;
[super dealloc];
}
@end
Это практически все, что вам нужно сделать, чтобы иметь успешную стратегию управления памятью. При использовании этого свойства всегда используйте средство получения / установки ( self.bogusString = [NSString stringWithString:@"bogus"];
) и убедитесь, что вы автоматически выпустили все, что выделили ( self.bogusString = [[[NSString alloc] initWithString:@"bogus2"] autorelease];
). Следуйте этому шаблону, и у вас не должно возникнуть никаких проблем.