Где я должен назвать [объектный выпуск]?

Я разделил некоторый UITextField на подклассы и добавил некоторые пользовательские свойства.

В UITableViewController, в ViewDiDLoad I init их, и в cellForRowAtIndexPath я добавляю их к ячейке с [cell.contentView addSubview:customTextField];

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

Где я должен звонить [customTextField выпуск]?

После того, как я добавляю их к представлению ячейки?

Если, например, я звоню [self.tableView reloadData], мои customTextField будут добавленными снова к ячейке, поэтому возможно, я должен изменить свой подход в выполнении этого?

спасибо за ориентацию...

с уважением,

r.

1
задан mongeta 3 May 2010 в 13:35
поделиться

7 ответов

Вы отпускаете объект, когда он больше не интересует вас. Это происходит по многим причинам; это может быть из-за того, что вы закончили работу с объектом или передали управление временем жизни объекта другому объекту. Это может быть потому, что вы собираетесь заменить объект новым экземпляром, это может быть потому, что вы (объект-владелец) собираетесь умереть.

Последнее, кажется, имеет отношение к вашему случаю. Вы создаете эти объекты в viewDidLoad и повторно нуждаетесь в них (т. Е. Для добавления их в ячейки), пока ваш объект не перестанет функционировать. В этом случае, так же, как вы создаете их в viewDidLoad , вы можете освободить их в viewDidUnload .

Изменить: я действительно должен упомянуть автозапуск , но в данном случае это не актуально. С управлением памятью лучше всего обращаться с понятием «владелец» - человек, который что-то создает (или сохраняет), должен нести ответственность за его удаление (или выпуск на языке ObjC). autorelease обрабатывают некоторые случаи, когда вам необходимо передать объект другому владельцу, который ранее владел им самостоятельно (обычно с помощью метода return). Если вы являетесь создателем, вы не можете просто выпустить его, прежде чем вернуть его новому владельцу, так как он будет удален до того, как новый владелец получит возможность заинтересоваться им. Однако вы не можете просто не выпустить его; он будет протекать. Таким образом, система предоставляет большой список объектов, которые она выпустит от вашего имени в какой-то момент в будущем.Вы передаете этому списку ответственность за выпуск , а затем возвращаете объект новому владельцу. Этот список (пул автозапуска) гарантирует, что ваш выпуск произойдет в какой-то момент, но дает новому владельцу возможность потребовать объект как свой, прежде чем он будет выпущен.

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

1
ответ дан 3 September 2019 в 00:52
поделиться

Самый безопасный способ управлять владением объектом - автоматически освобождать представление сразу после инициализации:

FooTextField* textField = [[[FooTextField alloc] init] autorelease];
[myCell.contentView addSubview:textField];

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

В сообществе разработчиков iPhone, похоже, есть недовольство автоматическим выпуском. На мой взгляд, это негодование безосновательно. Автосвобождение объекта добавляет очень мало накладных расходов программе, если объекты живут дольше, чем текущий проход через цикл выполнения.

0
ответ дан 3 September 2019 в 00:52
поделиться

Адам Райт очень хорошо объясняет теорию этого, но позвольте мне дать вам немного практики. Вы слишком много думаете над этой проблемой, а это почти всегда приводит к ошибкам. Есть простое решение, которое решает эту проблему почти всегда: Сохраняйте все ивары, используя аксессоры; не сохраняйте неивары.

.h

@interface ... {
    UITextField *_customTextField;
}

.m

@property (nonatomic, readwrite, retain) UITextField *customTextField;
...
@synthesize customTextField=_customTextField;

-(void)viewDiDLoad {
    self.customTextField = [[[UITextField alloc] init....] autorelease];
}
...
- (void)dealloc {
   // I do not recommend accessors in dealloc; but everywhere else I do
   [_customTextField release]; _customTextField = nil;
}

Никогда не обращайтесь к вашим ivars напрямую, за исключением dealloc (даже это спорно, и некоторые рекомендуют self.customTextField = nil; в dealloc; аргументы есть в любом случае). Но никогда не присваивайте свои ivars напрямую. Если вы будете следовать этому правилу, то обнаружите, что большинство ваших проблем с памятью исчезнут.

1
ответ дан 3 September 2019 в 00:52
поделиться

Каждый объект в Obj-C имеет счетчик ссылок (keepCount), и когда этот счетчик становится равным 0, объект освобождается. Когда вы выделяете и инициализируете объект, счетчик ссылок устанавливается на 1, но вы можете сохранять его столько раз, сколько захотите.

UITextField *textField = [[UITextField alloc] init]; // Reference counter = 1
[textField retain]; // Reference counter = 2
[textField retain]; // Reference counter = 3

Противоположность удержанию - это освобождение, которое вычитается из счетчика ссылок;

...
[textField release]; // Reference counter = 2
[textField release]; // Reference counter = 1

Вы всегда можете получить счетчик ссылок своих объектов;

printf("Retain count: %i", [textField retainCount]);

Метод addSubview из UIView ] сохраняет , переданный вами во вложенном представлении - и когда он с ним закончил, он освобождает его. Если вам понадобится ваш UITextField позже, в другой области (когда UIView закончен с ним и выпустил его) - вы не должны выпускать его после того, как вы » Я добавил его в супер-просмотр. В большинстве случаев вам действительно не нужно держаться за ссылку, поэтому вы должны освободить ее после того, как добавили в суперпредставление. Если вы этого не сделаете - вы можете освободить его в методе dealloc вашей области видимости.

0
ответ дан 3 September 2019 в 00:52
поделиться

Взгляните на UITableView -dequeueReusableCellWithIdentifier: и -initWithStyle: reuseIdentifier :.

В -tableView: cellForRowAtIndexPath: используйте -dequeueReusableCellWithIdentifier: и проверьте, равен ли результат нулю. Если это так, создайте экземпляр новой ячейки с помощью -initWithStyle: reuseIdentifier :.

Отправить -autorelease в customTextField после создания и добавления в соответствующую ячейку.

0
ответ дан 3 September 2019 в 00:52
поделиться

Вы не должны добавлять подпросмотр в cellForRowAtIndexPath! Это замедлит работу представления, поскольку вы добавляете вложенный вид каждый раз, когда отображается ячейка. Попробуйте использовать для этой цели пользовательский класс UITableViewCell.

Вот отличное решение по настройке UITableView http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html работает просто идеально

-1
ответ дан 3 September 2019 в 00:52
поделиться

Я всегда освобождаю свои элементы управления непосредственно после добавления их в представление с помощью addSubView. Когда я работаю с таблицами, я также инициализирую их в методе cellForRowAtIndexPath.

Таким образом, объект остается живым наименьшее время.

1
ответ дан 3 September 2019 в 00:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: