Правильная, управляемая памятью реализация пользовательского метода получения NSDictionary - PullRequest
0 голосов
/ 14 октября 2011

Заранее спасибо ...

Итак, после некоторых недавних утечек памяти и ошибок (задокументировано здесь ), я изучал управление памятью и сейчас пытаюсьнаписать собственный метод получения для NSDictionary в вспомогательном классе, который у меня есть.

Причины для специального метода получения:

Во-первых, это вычисляемый словарь, поэтому для проблем производительности я хочу вернутькэшированный объект, если только это не необходимо для его регенерации (мой пример ниже не слишком дорог для вычислений, но другие в классе будут).

Во-вторых, я хочу лениво создать экземпляр.Я хочу создать словарь только в том случае, если другой класс «запрашивает» его, поэтому я проверяю nil в получателе.

Итак, вопросы.Приведенный ниже код представляет мою первую (изученную) попытку написания собственного установщика / получателя, я обычно просто синтезирую.

1) Это правильная реализация и правильное управление памятью?

2) Этоbest?

3) Является ли BOOL installedStandardsChangedSinceLastRead лучшим способом обозначить необходимость пересчета?Это произошло бы, если бы другие методы в классе что-то изменили.Но я должен просто использовать вместо этих методов ноль из _installedStandards, так как это также вызовет перерасчет?

4) Наконец, если бы я сделал , просто бы другие методы обнулили iVarчтобы пометить его для пересчета, как я могу убедиться, что я не утечка?Буду ли я использовать сеттер (например, self.installedStandards = nil), ноль iVar напрямую (т. Е. _installedStandards = nil) или что-то еще?

(О, и если бы я ноль iVar напрямую, мне нужно было бысначала отпустите? Кажется, что правильно будет [_installedStandards release]; _installedStandards = nil? В таком случае я не могу просто использовать self.installedStandards = nil?)

На код! Напомним, что этоэто упрощенная версия того, что будет более сложным классом (см. ссылку вверху) с множеством этих методов установки / получения.Мне нужно убедиться, что я выполняю правильно, прежде чем я уточню это.

.h файл

@interface InstalledStandardTracker20 : NSObject {

    NSDictionary *_installedStandards;
    BOOL _installedStandardsChangedSinceLastRead;
}

@property (nonatomic, retain) NSDictionary *installedStandards;
@property (nonatomic) BOOL installedStandardsChangedSinceLastRead;

@end

@ реализация

@implementation InstalledStandardTracker20

@synthesize installedStandardsChangedSinceLastRead = _installedStandardsChangedSinceLastRead;

- (void)refreshInstalledStandards {
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    self.installedStandards = [currentDefaults objectForKey:@"installedStandards"];
    self.installedStandardsChangedSinceLastRead = NO;
}

- (NSDictionary *)installedStandards {
    if (!_installedStandards || self.installedStandardsChangedSinceLastRead) {
        [self refreshInstalledStandards];
    }
    return _installedStandards;
}

- (void)setInstalledStandards:(NSDictionary *)newInstalledStandards {
    [newInstalledStandards retain];
    [_installedStandards release];
    _installedStandards = newInstalledStandards;
}

1 Ответ

0 голосов
/ 14 октября 2011

На этот вопрос довольно сложно ответить, потому что вне класса нет контекста.Код выглядит без утечки памяти.Кроме того, вам не нужно реализовывать -setInstalledStandards :.Поскольку вы вызываете @synthesize для свойства retain, сгенерированный установщик будет выглядеть именно так.По сути, вы переопределяете метод точно таким же методом.

Что касается другого вопроса, исключение iVar не имеет никакого отношения к тому, какие объекты хранятся в памяти.Как только вы отпускаете iVar, объект по адресу памяти, указанному в вашем указателе, больше не гарантированно существует.Обнуляя iVar, вы просто сбрасываете тот адрес памяти, чтобы он указывал на ноль.Это позволяет избежать получения исключения EXC_BAD_ACCESS во время выполнения, поскольку никакие другие части вашей программы не будут пытаться получить доступ к этому теперь неопределенному адресному пространству.

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

...