массив словарей и mem mgmt

#iphone #objective-c

#iPhone #objective-c

Вопрос:

У меня есть массив словарей, который работает нормально. Я пытаюсь отследить проблему с доступом к памяти и хочу знать:

Если я создам автоматически выпущенные строки для словаря, например, одна строка будет из:

 NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:amp;error];
for (NSString *file in dirContents)
  

Когда я делаю

 NSDictionary *dictItem = [NSDictionary dictionaryWithObjectsAndKeys:file, @"file"...
  

Сохраняет ли результирующий dictItem отдельные строки? Я так и предполагал 😉

И затем я добавляю этот dictItem в массив. Я предполагаю, что вызов AddObject в NSMutableArray сохранит dictItem для меня…

Что насчет того, когда придет время освобождать память? Если я просто вызову removeAllObjects в массиве (который сейчас завершается сбоем), будет ли это освобождать все строки внутри словарей, а также сами словари?

Надеюсь, это в какой-то степени понятно 😉

Спасибо!

Ответ №1:

Вот краткий обзор управления памятью в Cocoa collections…

  • NSDictionary не сохраняет ключи. Вместо этого создается копия ключа. Другими словами, добавление объекта в качестве ключа в словаре не приведет к увеличению его количества сохранений.
  • NSDictionary сохранит значения для ключей, которые вы ему передаете.
  • Когда вы освобождаете (и в конечном итоге освобождаете) NSDictionary, он отвечает за вызов release для объектов, которые он сохранил (не вы!).
  • NSArray сохранит любой объект, который вы к нему добавите
  • NSArray освободит все объекты, на которые он содержит ссылку, когда он будет освобожден

Зная вышесказанное…

  • dicItem не сохранит ваш ключ @»file» — он скопирует его
  • dicItem сохранит ваш объект под названием file
  • когда dicItem будет освобожден, он вызовет release для своей копии @»file» и file
  • когда вы добавляете элемент в свой массив, он будет сохранен
  • когда вы освободите свой массив и он будет освобожден, всем содержащимся в нем элементам будет отправлено сообщение об освобождении
  • освобождение вашего массива должно впоследствии вызвать освобождение ваших объектов dicItem — при условии, что на них есть ссылки в другом месте (т. Е. утечка)
  • вам не нужно отправлять вашему объекту NSArray сообщение removeAllObjects — массив сам очистится после себя.

Комментарии:

1. Спасибо! В этом есть смысл! Похоже, я в основном использую его правильно, просто не знал, что было копией, а что сохранением. Диктанты — единственные необходимые копии для моего приложения. removeAllObjects должен был обрабатывать «обновление», когда я хочу повторно использовать массив.

Ответ №2:

Я думаю, вы делаете это немного сложнее, чем это должно быть. Единственное управление памятью, о котором вам действительно нужно беспокоиться, находится в ваших собственных классах. При добавлении в NSArray фактически сохраняется объект, а затем, когда вы вызываете removeAllObjects или массив уничтожается, он освобождает все содержащиеся в нем объекты. Однако именно здесь важна концепция «владения» объектом. Когда какой-либо объект получает ссылку на объект, он может вызвать для него «retain», чтобы указать, что он владеет объектом (это также относится к выделению нового объекта или использованию оператора «new»). Это означает, что объект точно знает, что объект будет рядом, пока с ним не будет покончено. Чтобы указать, что это сделано с объектом, он всегда должен освобождать или автоматически выпускать объект и устанавливать ссылку на nil .

Итак, в итоге, если вы не вызываете retain , alloc или new для объекта, вам никогда не следует вызывать release . Если вы вызываете одну из этих функций, вы всегда должны вызывать для нее release или autorelease. Для любого другого объекта, на который вы можете отправить ссылку, вы можете предположить, что он станет владельцем этого, если захочет, и если это произойдет, он всегда освободит его, когда это будет сделано.