#iphone #objective-c #retain
#iPhone #objective-c #сохранить
Вопрос:
мне интересно о поведении класса CALayer и его счетчика ссылок. Пожалуйста, ознакомьтесь со следующими двумя фрагментами кода:
Первый:
CALayer *layer = [[CALayer alloc] init];
NSLog(@"retain count: %d", [layer retainCount]); // log: retain count: 1
[layer release]; // no problem so far
[layer release]; // this leads to a crash as expected
Второй:
CALayer *layer = [[CALayer alloc] init];
NSLog(@"retain count: %d", [layer retainCount]); // log: retain count: 1
layer.opaque = YES; //increases the retain count, WHY?!?
NSLog(@"retain count: %d", [layer retainCount]); // log: retain count: 2
[layer release]; // no problem so far
[layer release]; // this leads NOT to a crash as expected
В первом фрагменте все происходит так, как я ожидаю, также сбой (зомби …) во втором сообщении о выпуске.
Во втором случае происходят неожиданные вещи. Вызов любого сообщения после инициализации (например, layer.opaque = YES) увеличивает счетчик сохранения на единицу, но только при первом вызове сообщения. Таким образом, счетчик сохранения всегда равен от 1 до максимума. Чтобы доказать, что это не просто проблема с числом, я использовал вторую версию. Слой будет освобожден из памяти только после второго выпуска.
Подобное поведение также может быть вызвано авторелизом.
Итак, почему сообщение для слоя увеличивает количество сохранений? Я пропустил какую-то информацию о проблемах с сохранением и выпуском?
Заранее спасибо
Марко
Ответ №1:
Вы пропустили часть о том, что для отладки не используется количество сохранений. Не делайте этого. Количество сохраняемых объектов — не ваше дело.
Сосредоточьтесь на своем праве собственности на объект. Если он принадлежит вам (сохранить, выделить, скопировать или создать), вы должны освободить его один раз.
Если объект остается после того, как вы правильно выполнили цикл сохранения / выпуска, это означает, что им владеет кто-то другой и несет ответственность за его выпуск. Если вы снова выпустите его, вы нарушите это право собственности, что может закончиться только трагически.
Итак, если layer.opaque = YES
количество сохранений увеличивается, позвольте этому. Не беспокойтесь об этом. Вы выполнили свое обязательство, и выполнение чего-либо еще приведет к нарушению баланса цикла сохранения / выпуска в другом месте.
Комментарии:
1. Спасибо за ваш ответ, но если я проигнорирую это, мое приложение переполнит память. Итак, я должен посмотреть, какая память не освобождена. Я разобрался с проблемой до этого момента. Если я дважды выпущу все CALayers, все будет работать нормально. Даже второй фрагмент в моем посте работает нормально (без создания зомби) при тестировании в одиночку. Это (призрачное) сохранение создается только в CALayer.
Ответ №2:
retainCount бесполезен. Не вызывайте это.
Итак, почему сообщение для слоя увеличивает количество сохранений? Я пропустил какую-то информацию о проблемах с сохранением и выпуском?
Потому что это внутренняя деталь реализации фреймворка.
Если вы сбалансируете свои сохранения и выпуски, то ваши объекты будут освобождены правильно.
Если объект задерживается слишком долго (достаточно долго, чтобы вызвать сбой вашего приложения), это потому, что ваш код неправильно все очищает. В случае слоев наиболее распространенной причиной является неспособность удалить слой из иерархии слоев / представлений, когда ваше приложение закончит с ним.