Уничтожает ли освобождение объекта объект?

#cocoa-touch #memory-management

#cocoa-touch #управление памятью

Вопрос:

Я новичок в cocoa-touch и действительно неуправляемых языках вместе взятых. Хотя я хорошо разбираюсь в синтаксисе, я сомневаюсь, правильно ли я освобождаю объект.

У меня есть представление, которое создает объект,

 Communication *comm = [[Communication alloc] init];
[comm doSomething];
[comm release];
  

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

Я вызываю метод для объекта, который отправляется на мой сервер и получает информацию. Когда данные возвращаются, это вызывает событие, на которое отвечает мой «диспетчер сообщений». Я не хочу уничтожать объект до тех пор, пока он не вернется обратно с сервера — и вот где мое замешательство.

  1. Если я выпущу этот объект непосредственно после выполнения вызова, уничтожит ли это объект? (Чего я не хочу делать.)
  2. Как мне правильно уничтожить этот объект после того, как он вызовет событие с данными, которые я ожидаю? Это произошло бы в рамках DataFinishedLoading события на моем comm объекте. Должен ли он уничтожать сам себя, и является ли это правильным способом сделать это?

Представление, вызывающее мой объект, по сути, говорит: создайте этот объект, вызовите этот метод и идите своим путем. Его не волнует, что происходит после вызова метода — возвращает ли он информацию или нет. Он просто прослушивает метод для любых данных, которые могут появиться позже. У меня нет причин цепляться за ссылку на объект, поскольку я никогда не буду использовать тот же экземпляр после выполнения вызова — это помимо уборки за собой.

Ответ №1:

A release уничтожает объект только в том случае, если его освободил последний фиксатор.

Допустим, вы выделяете свой Communication объект. Он неявно сохраняется один раз. Затем вы сохраняете его пять раз. Вам нужно освободить / авторелизировать объект шесть раз, пока он не будет уничтожен (вызывается его dealloc метод).

Существует внутренний счетчик, retainCount . Когда вы создаете объект, ему присваивается значение 1 . Теперь каждый retain увеличивает счетчик, и каждый release уменьшает его. autorelease также уменьшает счетчик, но не сразу. Как только счетчик падает до 0, Objective-C знает, что объект больше не нужен, и уничтожает его (вызывая объект dealloc ). Предупреждение: не полагайтесь на retainCount , даже не смотрите на него. Вы должны заботиться только о том, чтобы ваши alloc/copy/new/retain вызовы были сбалансированы с соответствующими release/autorelease позже.

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

1. Возможно ли настроить мой объект связи на автоматическое освобождение после его завершения?

2. @George: Вы можете сделать comm = [[[Communication alloc] init] autorelease]; , и как только вы покинете метод, в котором вы это сделали, объект будет освобожден один раз (но вы не знаете, когда, и вам не нужно беспокоиться). Вы, вероятно, имеете в виду, я хочу, чтобы объект исчез, как только он закончил свою работу . Это сложнее. Лучший метод — каким-то образом сообщить, что работа выполнена (например, с помощью метода делегирования), и заставить создателя объекта освободить его. Но объект не должен делать [self release]; или что-то в этом роде, если вы это имеете в виду. Хотя это возможно, это плохой стиль и сбивает с толку.

3. После того, как я вызову объект из своего представления и данные будут возвращены позднее, объект связи сообщит моему делегату приложения, что что-то пришло с моего сервера по подписке. На этом этапе объект связи выполнил всю свою работу и больше никогда не понадобится — по крайней мере, этот его экземпляр. Уместно ли освобождать его там? Или это [саморазгружение], против которого вы советуете?

4. @George: Вы бы сделали это следующим образом: контроллер выделяет его с [[Communication alloc] init]; и сохраняет в переменной экземпляра. Вы не вызываете release здесь. Я предполагаю, что этот контроллер является делегатом. Ваш объект завершает работу, затем вызывает делегата / контроллер. Теперь контроллер вызывает release объект связи (и также устанавливает переменную в nil значение).

Ответ №2:

В приведенном выше примере он, comm скорее всего, будет уничтожен при вашем вызове . ………. release Это зависит от того, что что-то еще сохраняет его во время doSomething .

Если вы хотите сохранить объект, пока он выполняет что-то асинхронно, поместите его в свойство retained. Когда он сообщит вам, что это сделано, установите свойство на nil , которое его освободит.