Ответ 1
Это очень хороший вопрос, я подождал несколько часов в надежде, что кто-то даст достаточный ответ, но поскольку никто даже не ответил, я попробую. Сначала я прокомментирую ваш подход, затем я попытаюсь предложить, как бы я обошел это.
Это определенно очень плохая идея для выпуска - таким образом освободить объект от его делегата. Просто подумайте о том, как объекты (например, CLLocationManager) звонят своим делегатам - они просто называют их посредине некоторого метода. Когда вызов делегата завершен, выполнение кода возвращается к методу объекта, который уже был освобожден. BAM!
Остановитесь на мгновение о том, что это плохая идея. Я вижу два варианта, как легко это исправить. Во-первых, autorelease
вместо release
дает объекту немного более продолжительный спам - он, по крайней мере, выживет, вернувшись из делегата. Этого должно быть достаточно для большинства случаев, по крайней мере, если автор API хорошо выполнил свою работу и инкапсулировал логику основного класса API (в случае CLLocationManager он может ожидать, что GPS отключится...). Второй вариант заключается в задержке выпуска (performSelector:withObject:afterDelay:
приходит на ум), но это более обходное решение для плохо реализованных API.
Итак, если выпускать это не очень хорошая идея, то что?
Что вы на самом деле получаете, выпустив CLLocationManager? Освобождение этих нескольких байтов памяти не спасет ваше приложение от завершения, когда система потеряла память. В любом случае, действительно ли это только один раз, когда вам нужно текущее местоположение пользователя?
Я предлагаю вам инкапсулировать задачи, связанные с CLLocationManager, в отдельный класс, возможно, даже в singleton - этот класс станет его делегатом, и он позаботится об общении с CLLocationManager и сообщит вашей заявке о результатах (возможно, отправив NSNotification
). CLLocationManager будет освобожден из этого класса dealloc
и никогда не будет вызван обратным вызовом делегата. stopUpdatingLocation
должно хватить, освобождая несколько байтов памяти - ну, вы можете сделать это, когда ваше приложение вводит фон, но пока ваше приложение работает, освобождение этих нескольких байтов не приводит к существенному улучшению потребления памяти.
** Добавление **
Естественно и правильно, чтобы делегат имел право собственности на объект, для которого он выступает в качестве делегата. Но делегат не должен освобождать объект в результате обратного вызова. Однако есть одно исключение из этого, и это обратный вызов, говорящий о завершении обработки. Для примера это NSURLConnection
connectionDidFinishLoading:
, который указывается в документации "Делегат не получит никаких дополнительных сообщений". У вас может быть класс, загружающий кучу файлов, каждый из которых имеет другой NSURLConnection
(имеющий свой класс в качестве делегата), выделяя и отпуская их в процессе загрузки файлов.
CLLocationManager
поведение отличается. В вашей программе должен быть только один экземпляр CLLocationManager. Этот экземпляр управляется некоторым кодом, возможно, одним синглэном, который может быть выпущен, когда приложение переходит в фоновый режим, повторно инициализируется при просыпании. CLLocationManager
срок службы будет таким же, как и для его управляющего класса, который также действует как делегат.