2011-06-29 2 views
1

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

__block Loader *loader = [[Loader alloc]initWithResourcePath:self.resourcePath]; 

[loader setCompletionHandler:^(NSArray *anArray){ 
    self.answerArray=anArray; 
    [self reloadData]; 

}]; 

[loader getObjects]; 

Мой вопрос в отношении управления памятью. Анализатор сообщает мне, что существует потенциальная утечка (поскольку я использовал alloc/init для моего загрузчика). Как я могу остановить утечку здесь? Я попытался выпустить загрузчик в конце, но это заставляет мое приложение перестать функционировать. Любые рекомендации оцениваются здесь

+0

Прекратить функционирование КАК? Какая ошибка вы получаете? Скорее всего, это поможет вам найти причину вашей проблемы. –

+0

Есть ли причина, по которой вы объявили загрузчик как __block? –

ответ

3

Несколько вопросов:

  • нет никакой причины для loader быть объявлены __block; вы не переустанавливаете в блоке и, таким образом, __block бессмысленны.

  • утечка происходит потому, что вы alloc/init загрузчик, но никогда не выпустит его

  • не называют Методы getSomething; префикс get зарезервирован для методов, возвращающих материал по ссылке. Просто назовите его objects. Если предполагается запуск нагрузки, то назовите ее load или performLoad.

Если это асинхронно, то getObjects бессмысленно. Если синхронно, то блок завершения бесполезен.

Если loader будет использоваться синхронно, release это в конце метода. Если это asynchronous, то блок завершения может его освободить.Обратите внимание, что использование __block в этом случае по-прежнему бессмысленно; в то время как ссылка на loader в блоке завершения будет создавать цикл удержания, он будет разорван, когда вы явно заблокируете блок() в своем loader (потому что вы должны сделали при настройке обработчика завершения, если он будет использоваться асинхронно в первую очередь).

+0

Я прочитал его на веб-сайте ASIHTTPRequest (http://allseeing-i.com/ASIHTTPRequest/How-to-use), что важно использовать квалификатор __block, когда мы объявляем запрос. Но могу ли я сказать, что этот пример имеет значение, потому что они фактически использовали запрос в блоке? – Zhen

+0

Да, по причине, описанной выше, только они решили не освобождать блок, когда соединение завершено или с ошибкой (I.e. Как только блок больше не будет вызываться), создавая таким образом цикл. Я выбираю использовать шаблоны, где циклы автоматически разбиваются как часть жизненного цикла объекта. – bbum

1

Если вы планируете использовать loader вне функции, вызывающей ваш блок, очень возможно, что вам нужно сохранить его в ivar вашего контроллера (я думаю, это контроллер, но я не знаю, какой класс владеет кодом, который вы показываете). Как только вы это сделаете, вы можете освободить его в своем dealloc.

Причина в том, что loader должен взаимодействовать с несколькими методами и циклами runloop, поэтому локальная переменная не будет работать.

В противном случае просто отпустите его в конце блока, как только вы это сделаете.

Если это не похоже на вас, возможно, потребуется больше кода.

1

Я собираюсь сделать некоторые предположения: 1) Обработчик завершения (блок) используется методом getObjects. 2) getObjects является асинхронным (он сразу возвращается к вызывающему, хотя он продолжает обрабатываться).

С этими предположениями вы не можете отправить выпуск после отправки getObjects, поскольку getObjects все еще использует обработчик завершения.

Попробуйте отправить выпуск или авторейтинг в конце обработчика завершения. Это означает, что бесплатный загрузчик предоставляется reloadData не является асинхронным.

Смежные вопросы