Почему я должен отправлять -autorelease моей переменной экземпляра в моем методе установки, а не -release? - PullRequest
1 голос
/ 26 апреля 2009

Apple делает это в методе установки для переменной экземпляра mainSprocket:

– (void)setMainSprocket:(Sprocket *)newSprocket {
    [mainSprocket autorelease];
    mainSprocket = [newSprocket retain];
    return;
}

Почему они посылают -авторелизу, а не -релиз? Будет ли -релиз иметь плохой эффект здесь? На самом деле это не должно (для моего понимания), потому что -release просто говорит, что текущий объект, содержащийся в переменной экземпляра mainSprocket, больше не используется этой переменной экземпляра. В случае, если кто-то еще все еще интересуется именно этим объектом, этот метод может сохранить его, верно? Значит, выпуск должен быть в порядке, я думаю?

Ответы [ 2 ]

4 голосов
/ 26 апреля 2009

Если mainSprocket и newSprocket - это один и тот же объект, он может быть освобожден, если вы используете простой release.

Если вы не хотите использовать autorelease, используйте это:

– (void)setMainSprocket:(Sprocket *)newSprocket {
    // if newSprocket and mainSprocket were the same object, 
    // it would first be retained and then released
    // and therefore not deleted.
    [newSprocket retain];
    [mainSprocket release];
    mainSprocket = newSprocket;
    // you don't need return in a void-method
    // return;
}

Почему вы не используете свойства? Это способ Objective-C 2.0.

SomeObject.h

@interface SomeObject : NSObject {
    Sprocket *mainSprocket;
}

@property(retain) Sprocket *mainSprocket;

@end

SomeObject.m

@implementation SomeObject

@synthesize mainSprocket;

@end
3 голосов
/ 26 апреля 2009

Они делают autorelease здесь на случай, если newSprocket и mainSprocket окажутся одним и тем же объектом. Вызов release может непреднамеренно освободить объект, прежде чем его можно будет сохранить на следующей строке, тогда как autorelease не будет обрабатываться до тех пор, пока пул автообновления не будет слит в конце цикла событий.

Рассмотрим этот сценарий:

Sprocket *mySprocket = [Sprocket spacelySprocket];
[sprocketManager setMainSprocket:mySprocket];

Sprocket *anotherPointerToMySprocket = mySprocket;
[sprocketManager setMainSprocket:anotherPointerToMySprocket];

Последняя строка вызовет проблему, если mainSprocket не будет автоматически выпущен. Другое соглашение, которое вы иногда можете увидеть для установочного кода, который делает то же самое:

– (void)setMainSprocket:(Sprocket *)newSprocket {
    if (newSprocket != mainSprocket) {
        [mainSprocket release];
        mainSprocket = [newSprocket retain];
    }
}

Я оставлю это на усмотрение других, чтобы прокомментировать, что является более подходящим или эстетически приятным: -)

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