Почему моя собственность является потенциальной утечкой и как я могу это исправить? - PullRequest
1 голос
/ 13 августа 2011

У меня есть UIScrollView в моем UIViewController , определенном как это в моем файле .h:

#import <UIKit/UIKit.h>

@interface TestViewController : UIViewController <UIScrollViewDelegate>

@property (nonatomic, retain) UIScrollView * imageScrollView;

@end

Затем в моем файле .m у меня есть следующее:

@synthesize imageScrollView = _imageScrollView;

Я прочитал, что это автоматически создаст _imageScrollView, который я обычно печатаю в файле .h?(UIScrollView * _imageScrollView)

Мне это нравится, потому что он удаляет дублирующийся код из моих .h файлов.Теперь в моем loadView я делаю все остальное:

self.imageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)];
[_imageScrollView setDelegate:self];
[_imageScrollView setPagingEnabled:YES];
[_imageScrollView setBounces:NO];
[_imageScrollView setShowsHorizontalScrollIndicator:NO];
[_imageScrollView setShowsVerticalScrollIndicator:NO];
[_imageScrollView setContentSize:CGSizeMake(320.0 * 3.0, 480.0 - 20.0 - 49.0)];

И в выпуске dealloc и nil:

- (void)dealloc
{
[_imageScrollView release], _imageScrollView = nil;

[super dealloc];
}

Теперь послеbuild Xcode говорит мне это:

Potential leak of an object allocated on line #linenumber

Это пройдет, когда я изменю это:

self.imageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)];

на это:

self.imageScrollView = [[[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)] autorelease];

Зачем мне это нужно?автоматически выпустить это, когда я выпущу его в dealloc?Что я делаю не так?

Это предупреждение о памяти появляется только в Xcode на моем iMac с установленным Lion, а не на моем macbook со снежным барсом ...

Ответы [ 2 ]

2 голосов
/ 13 августа 2011

Вы определили свою собственность с опцией retain. Это означает, что когда вы назначаете объект этому свойству, он будет сохранен - ​​вы «станете владельцем» объекта. Это хорошо в этом случае, потому что вы хотите, чтобы UIScrollView оставался рядом, пока вам это нужно. Я должен отметить, что у вас также есть любой объект, возвращенный из методов, имя которых начинается с alloc, new, copy или mutableCopy.

Итак, глядя на ваш код, вы можете видеть, что вы владеете UIScrollView, который вы создаете с помощью alloc, но затем вы снова заявляете о владении при сохранении его в свойстве. Это означает, что память никогда не будет восстановлена. Вызывая autorelease, вы отказываетесь от владения объектом до того, как присваиваете его свойству, что означает, что вызов release в dealloc будет работать так, как задумано.

Я предлагаю вам прочитать Руководство по программированию управления памятью и Объявленные свойства в документе Objective-C. Язык программирования.

2 голосов
/ 13 августа 2011

Это потому, что ваше свойство imageScrollView объявлено как свойство retain.Это означает, что при его установке средство доступа (генерируемое @synthesize) автоматически сохраняет значение.Если вы не хотите, чтобы такое поведение, вы должны объявить ваше свойство assign.(Но вы действительно хотите такое поведение в этом случае.)

В любом случае, таким образом, ваш объект сохраняется дважды, один раз в вашем коде и один раз средством доступа, поэтому он никогда не освобождается.Всегда помните, что self.imageScrollView = точно так же, как [self setImageScrollView:], и что-то там происходит!

(И последнее, предупреждение о памяти появляется только на Lion, потому что старый Xcode не замечает ошибку, а не потому, чтоошибки нет.)

...