Цель-C: освобождение объекта от самого себя - PullRequest
2 голосов
/ 08 июля 2011

Я наткнулся на интересную ситуацию, когда объект мог выпустить себя, и ему было интересно, что считается безопасным и правильным в этой ситуации.

Представьте, что у нас есть класс Foo:

@implementation Foo
+ (Foo *) foo {
    return [[[Foo alloc] init] autorelease];
}

- (void)resign {
    [FooHolder holder].foo = nil;

    // here's where the things happen
}
@end

Еще одним классом является FooHolder (синглтон с одним свойством):

@interface FooHolder : NSObject {
    Foo *foo;
}

@property (retain) Foo *foo;

+ (FooHolder *)holder;

@end

И где-то в коде мы делаем это (вызывая сначала stepOne, а затем stepTwo; пулы авто-выпуска очищаются после завершения stepOne):

- (void)stepOne {
    Foo *foo = [Foo foo];

    [FooHolder holder].foo = foo;
}

- (void)stepTwo {
    [[FooHolder holder].foo resign]
}

Если я пытаюсь получить доступ к self в методе resign, после назначения с помощью NSZombieEnabled я получаю предупреждение о том, что self уже освобожден.Это дает мне короткий WTF момент, но хорошо, я могу жить без доступа к self в этой части.Что беспокоит меня больше, если объект уже освобожден, кто может гарантировать, что стек не поврежден, и мы нормально работаем с нашими локальными переменными и переменными экземпляра?В целом, является ли плохой практикой разрешать освобождение self в методе?

Ответы [ 2 ]

5 голосов
/ 08 июля 2011

В целом, является ли плохой практикой позволять освобождать себя, находясь в методе?

Да, потому что с момента освобождения себя все ваши ивары также могут быть освобождены.

Я не буду притворяться, что понимаю ваш дизайн или причины, по которым вы это делаете, но почему вы не изменили свой метод отставки:

- (void)resign {
    // here's where the things should happen
    [FooHolder holder].foo = nil;
}

Вы должны всегда освобождать собственные объекты после того, как есть вероятность, что вы будете использовать их так же, как вы вызываете [super dealloc]; в end из -(void)dealloc

3 голосов
/ 08 июля 2011

Я бы сказал, что у вас неправильный дизайн. В методе экземпляра -resign вы фактически освобождаете конкретный экземпляр foo, удерживаемый синглтоном. Почему любой произвольный экземпляр foo делает это? Ссылка на то, что фактически является глобальной переменной в методе экземпляра, делает связь слишком тесной.

Что бы ни вызывало -resign, это должно быть то, что говорит [FooHolder holder], что он отказался от foo или откажется от foo. Альтернативно, иметь слабую ссылку на FooHolder в foo и заставить foo отправить ему сообщение, подобное -willResign:(Foo*). Это фактически делает его делегатом foo. В -willResign: FooHolder может проверить, является ли он правильным foo, а затем сохранить и автоматически выпустить его, прежде чем установить в ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...