Управление памятью iPhone - PullRequest
       2

Управление памятью iPhone

2 голосов
/ 14 января 2011

Я новичок в программировании iPhone. Я не использую Interface Builder в моем программировании. У меня есть некоторые сомнения по поводу управления памятью, @property темы в iPhone. Рассмотрим следующий код

@interface LoadFlag : UIViewController {
  UIImage *flag;
  UIImageView *preview;

}

@property (nonatomic, retain) UIImageView *preview;
@property (nonatomic, retain) UIImage *flag; 

...   

@implementation LoadFlag
@synthesize preview;
@synthesize flag;

- (void)viewDidLoad
{
  flag = [UIImage imageNamed:@"myImage.png"]];
  NSLog(@"Preview: %d\n",[preview retainCount]); //Count: 0 but shouldn't it be 1 as I am retaining it in @property in interface file
  preview=[[UIImageView alloc]init];
  NSLog(@"Count: %d\n",[preview retainCount]); //Count: 1 
  preview.frame=CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
  preview.image = flag; 
  [self.view addSubview:preview];
  NSLog(@"Count: %d\n",[preview retainCount]); //Count: 2
  [preview release];
  NSLog(@"Count: %d\n",[preview retainCount]); //Count: 1
}

...
  1. Когда и почему (зачем) нужно установить @property с помощью retain (в вышеприведенном случае для UIImage & UIImageView)? Я видел это утверждение во многих примерах программ, но не понимал его необходимости.

  2. Когда я объявляю оператор @property (nonatomic, retain) UIImageView *preview;, счетчик сохранения равен 0. Почему он не увеличивается на 1, несмотря на сохранение его в @property.

  3. Кроме того, когда я объявляю [self.view addSubview:preview];, тогда снова сохраняю увеличение числа единиц на 1. В этом случае пул авто-релизов будет выпущен для нас позже, или мы должны позаботиться о его выпуске. Я не уверен, но я думаю, что Autorelease должен справиться с этим, поскольку мы явно не сохранили его, так почему мы должны беспокоиться о его выпуске.

  4. Теперь, после оператора [preview release]; мой счет равен 1. Теперь мне больше не нужно UIImageView в моей программе, поэтому, когда и где я должен его освободить, чтобы счетчик стал равен 0, и память стала перераспределена. Опять же, я не уверен, но я думаю, что Autorelease должен справиться с этим, поскольку мы явно не сохранили его, так почему мы должны беспокоиться о его выпуске. Что произойдет, если я выпущу его в -(void) dealloc метод

  5. В утверждении -> flag = [UIImage imageNamed:@"myImage.png"]]; Я не выделил памяти для пометки, но как я все еще могу использовать ее в своей программе. В этом случае, если я не выделяю память, то кто выделяет и освобождает память для нее, или это «флаг» просто ссылка, указывающая на -> [UIImage imageNamed:@"myImage.png"]];. Если это только ссылка, то нужно ли ее выпускать.

Ответы [ 5 ]

2 голосов
/ 15 января 2011

Вы говорите ...

Я новичок в программировании iPhone.Я не использую Интерфейсный Разработчик в моем программировании.

Подождите.Какие?Почему бы и нет? Не использование IB как новичка в среде - это, как правило, признак того, что вы делаете свое приложение нелегко.Неиспользование IB для разработки приложений зарезервировано для редких, как правило, довольно сложных ситуаций.

1 голос
/ 14 января 2011

Вопрос 1

Это означает, что сообщения доступа к синтезированным свойствам будут включать автоматическое сохранение при вызове сообщения (но ТОЛЬКО при вызове сообщения, см. Далее).

Вопрос 2

Это потому, что вы не используете сообщение доступа к свойству, а просто присваиваете переменную-член.Если вы используете:

self.preview = [[[UIImageView alloc] init] autorelease];

Итоговый счет удержания будет равен единице (+1 для init, -1 для автоматического выпуска, +1 для сохранения в сообщении).

NB

Вы получите тот же счет хранения (один), если сделаете это:

preview = [[UIImageView alloc] init];

(+ 1 для инициализации, без использования сообщения доступа к свойству, поэтому нет дополнительного сохранения).В зависимости от того, как вы поступите.

Вопрос 3

addSubview снова увеличит счет сохранения, поскольку preview будет сохранен вколлекция, которая будет сохранять свои объекты.

Так что да, в основном, если вы передаете объект другому объекту для управления (как в случае с addSubview), вы можете установить его на автоматический выпуск, и он будет освобожден другим объектом.Однако, поскольку вы сохраняете UIImageVIew в сохраненном свойстве, вам нужно будет разблокировать его самостоятельно (см. Далее).

Вопрос 4

Поскольку вы сохраняетеПредварительный просмотр объекта как сохраненного свойства, вам нужно будет опубликовать его в сообщении Deloc.Таким образом, в моем примере Question 2 вы выделяете объект, автоматически освобождаете его, но присваиваете ему сохраняемое свойство, так что после счетчика retain после всего этого вы добавляете его в коллекцию, которая также сохраняетЭто.Когда представление очищено, коллекция уменьшит счет сохранения, но вам также потребуется вызвать release, потому что вы сохранили его в сохраненном свойстве.Итак, в вашем dealloc:

[preview release];

Вопрос 5

imageNamed - это вспомогательное сообщение, которое выполняет выделение, инициализацию и авто-выпуск.Таким образом, в основном это эквивалентно высказыванию.

NSData * dataForImage = get data from the myImage.png here ...
self.flag = [[[UIImage alloc] initWithData:dataForImage] autorelease];

Вы сохраняете его в сохраненном свойстве (потому что я использую self.flag в приведенном выше примере), поэтому вам нужно будет отпустить его в сообщении dealloc.

1 голос
/ 14 января 2011

Когда вы пишете

 flag = [UIImage imageNamed:@"myImage.png"]];

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

 self.flag = [UIImage imageNamed:@"myImage.png"]];

Это объясняет вашу проблему сохранения количества.

Я считаю полезным объявить переменные экземпляра с другим именем, например _flagдля имущества flag.Свяжите их, написав

@property .... flag = _flag;

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

0 голосов
/ 20 января 2011

Вопрос 2. Оператор @property в вашем @interface - это на самом деле просто директива для компилятора, автоматически генерирующая методы доступа для переменной экземпляра, которая имеет указанные вами характеристики.@property не вызывает никаких действий при запуске вашего кода.Компилятор посмотрит строку @property и сгенерирует для вас невидимый код доступа.

@property (nonatomic, retain) UIImageView *preview;

заставит компилятор генерировать методы доступа, которые выглядят примерно так:

- (void) setPreview:(UIImageView *)newValue {
   [self willChangeValueForKey:@"preview"];
   if (preview != newValue) {
     [preview release];
     preview = [newValue retain];
   }
   [self didChangeValueForKey:@"preview"];
}

- (UIImageView *) preview {
   return preview;
}

@собственность экономит время;он указывает компилятору генерировать код доступа для ваших переменных, которые эффективны, но невидимы.Если вы не используете @property, вам придется написать методы доступа, аналогичные описанным выше, в вашем пользовательском классе.

0 голосов
/ 14 января 2011
  1. Вы используете retain, чтобы претендовать на право собственности на объект.По сути, это означает, что когда что-то присваивается свойству, вы гарантируете, что оно существует до тех пор, пока это необходимо для объекта-владельца.

  2. @property ... - это выражение вашего интерфейсатвой класс.Это не означает, что существует значение для рассматриваемого свойства, только то, что «Экземпляры LoadClass имеют свойство flag, которое сохраняется им».Только когда вы фактически назначите значения свойствам экземпляра, вещи будут сохранены.

  3. Это потому, что UIView претендует на владение своими подпредставлениями.

  4. Ваш объект может не нуждаться в этом, но UIView все еще нуждается в нем.

  5. Он автоматически выпущен UIImage.

Вы должны прочитать полное руководство на Управление памятью от Apple.Я пытаюсь думать об управлении памятью как о владении объектами или нет ... это помогает.

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