Objective-C связанные объекты утечки под ARC
Я столкнулся со странным objc_setAssociatedObject
поведение под ARC. Рассмотрим следующий код:
static char ASSOC_KEY;
@interface DeallocTester : NSObject
@end
@implementation DeallocTester
- (void) dealloc
{
NSLog(@"DeallocTester deallocated");
//objc_setAssociatedObject(self, &ASSOC_KEY, nil, OBJC_ASSOCIATION_RETAIN);
}
@end
@implementation AppDelegate
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
NSObject *test = [[DeallocTester alloc] init];
objc_setAssociatedObject(test, &ASSOC_KEY, [[DeallocTester alloc] init],
OBJC_ASSOCIATION_RETAIN);
}
Я создаю экземпляр DeallocTester
тогда я поставил другую DeallocTester
как связанный объект для него, то оба они выходят из области видимости.
Я ожидаю -dealloc
первого объекта, который будет вызван, затем связанный объект, который будет освобожден, но я вижу "DeallocTester deallocated"
сообщение печатается только один раз. Если я раскомментирую objc_setAssociatedObject
линия в -dealloc
, второй объект также освобождается.
Ссылка Objective C указывает, что связанные объекты автоматически освобождаются после уничтожения объекта. Это компилятор /ARC/ любой другой вопрос или я что-то упустил?
Обновить
Этот пример кода на самом деле работает, если вы запускаете его из совершенно нового проекта. Но у меня есть два проекта с поддержкой ARC, где этого нет. Я сделаю небольшое исследование и предоставлю лучший образец.
Обновление 2
2 ответа
Я нашел источник проблемы - у меня было NSZombie
объекты включены в обоих моих проектах, где эта ошибка появляется.
Насколько я понимаю, когда объекты зомби включены, нормальные экземпляры заменяются на NSZombie
после освобождения, но все связанные объекты остаются в живых! Остерегайтесь такого поведения!
Я создал rdar://10636309
Обновление: есть обходной путь Cédric Luthi, и эта проблема, кажется, исправлена в iOS 6.
Код, который вы разместили, работает точно так же, как рекламируется в ARC. Я переписал твой dealloc
реализация, чтобы помочь сделать вещи немного более очевидными.
- (void)dealloc
{
NSLog(@"deallocating %@", self);
}
Вот итоговый журнал:
2012-01-03 06:49:39.754 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x6878800>
2012-01-03 06:49:39.756 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x688b630>
Вы уверены, что компилируете с включенным ARC?