Основная проблема, связанная с памятью, о которой вам еще нужно знать, это сохранение циклов. Это происходит, когда один объект имеет сильный указатель на другой, но целевой объект имеет сильный указатель на оригинал. Даже если все другие ссылки на эти объекты будут удалены, они все равно будут держаться друг за друга и не будут освобождены. Это также может происходить косвенно, когда цепочка объектов может иметь последний в цепочке, ссылающийся на более ранний объект.
Именно по этой причине существуют __unsafe_unretained
и __weak
классификаторы собственности. Первый не будет сохранять какой-либо объект, на который он указывает, но оставляет открытой возможность того, что этот объект исчезнет, и он указывает на плохую память, тогда как последний не сохраняет объект и автоматически устанавливает ноль, когда его цель освобождается. Из них, __weak
как правило, предпочтительнее на платформах, которые его поддерживают.
Вы бы использовали эти квалификаторы для таких вещей, как делегаты, когда вы не хотите, чтобы объект сохранял свой делегат и потенциально приводил к циклу.
Еще одна важная проблема, связанная с памятью, - это обработка объектов Core Foundation и памяти, выделенной malloc()
для таких типов, как char*
. ARC не управляет этими типами, а только объектами Objective-C, поэтому вам все равно придется разбираться с ними самостоятельно. Базовые типы Foundation могут быть особенно хитрыми, потому что иногда их необходимо соединить с соответствующими объектами Objective-C и наоборот. Это означает, что контроль должен быть передан назад и вперед от ARC при соединении между типами CF и Objective-C. Были добавлены некоторые ключевые слова, связанные с этим мостовым соединением, и Майк Эш имеет большое описание различных случаев мостового соединения в своей длительной рецензии на ARC .
В дополнение к этому, есть несколько других менее частых, но все еще потенциально проблемных случаев, которые публикуются в спецификации подробно.
Большая часть нового поведения, основанного на хранении объектов, пока на них есть четкий указатель, очень похожа на сборку мусора на Mac. Тем не менее, технические основы очень разные. Вместо того, чтобы иметь процесс сборщика мусора, который запускается через регулярные промежутки времени для очистки объектов, на которые больше не указывают, этот стиль управления памятью опирается на жесткие правила сохранения / освобождения, которые мы все должны соблюдать в Objective-C.
ARC просто берет повторяющиеся задачи по управлению памятью, которые нам приходилось выполнять годами, и выгружает их в компилятор, поэтому нам больше не нужно о них беспокоиться. Таким образом, у вас не будет проблем с остановкой или профилей памяти пилообразной памяти, возникающих на платформах для сбора мусора. Я испытал оба этих фактора в своих приложениях Mac для сбора мусора, и мне не терпится увидеть, как они ведут себя в ARC.
Чтобы узнать больше о сборке мусора и ARC, посмотрите этот очень интересный ответ Криса Латтнера в списке рассылки Objective-C , где он перечисляет многие преимущества ARC по сравнению с сборкой мусора Objective-C 2.0. Я столкнулся с несколькими проблемами GC, которые он описывает.
ARC не поможет вам с не-ObjC памятью, например, если вам
malloc()
что-то нужно, вам все равно это нужноfree()
.ARC может быть обманут,
performSelector:
если компилятор не может понять, что это за селектор (компилятор выдаст предупреждение об этом).ARC также будет генерировать код в соответствии с соглашениями об именах ObjC, поэтому, если вы смешаете код ARC и MRC, вы можете получить удивительные результаты, если код MRC не будет выполнять то, что обещает компилятор в именах.
источник
В приложении возникли утечки памяти из-за следующих 4 проблем:
К счастью, я наткнулся на следующий пост в блоге и смог их исправить: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/
источник
ARC также не будет управлять типами CoreFoundation. Вы можете «соединить» их (используя
CFBridgingRelease()
), но только если вы собираетесь использовать его как объект Objective-C / Cocoa. Обратите внимание, что CFBridgingRelease просто уменьшает счетчик CoreFoundation на 1 и перемещает его в ARC Objective-C.источник
Xcode 9 предоставляет отличный инструмент для поиска подобных проблем. Он называется: « Граф отладочной памяти ». Используя его, вы можете найти свой просочившийся объект по типу класса и четко увидеть, кто на него ссылается, выпуская его оттуда, решает вашу проблему. Он также обнаруживает циклы памяти.
Смотрите больше информации о том, как его использовать
источник