Цель C NSMutableDictionary управления памятью - PullRequest
0 голосов
/ 01 апреля 2011

У меня есть класс модели, который хранит записи о дорожках, создаваемые несколькими представлениями.У него есть NSMutableDictionary, который имеет поля и значения, которые я в конечном итоге записываю в базу данных.Он сохраняется в листе и при необходимости загружается обратно.Я думал, что отслеживаю свою память, но она выдает EXC_BAD_ACCESS, когда я пытаюсь выпустить словарь.Вот мой интерфейс:

#import <Foundation/Foundation.h>


@interface CurrentEntryModel : NSObject {
 NSMutableDictionary *currentEntry;
}

@property (nonatomic, retain) NSMutableDictionary *currentEntry;
- (void) setValue: (NSString *)value;
- (NSString *) getValue;

@end

Я понимаю, что currentEntry должен быть сохранен, и мне пришлось бы освободить его во время dealloc.

Вот моя реализация (это не весь класстолько соответствующие части):

#import "CurrentEntryModel.h"


@implementation CurrentEntryModel

@synthesize currentEntry;

-(id) init {
    if ( self = [super init] )
    {
    //check for file
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *file;
    file = @"location.plist";

    if ([fileManager fileExistsAtPath:file]){ 
        NSLog(@"file exists");
        currentEntry = [[NSMutableDictionary alloc] initWithContentsOfFile:file];

    }else {
        NSLog(@"file doesn't exist");
        currentEntry = [[NSMutableDictionary alloc ] initWithCapacity:1];

        NSDate *testDate = [NSDate date];

        [currentEntry setObject:testDate forKey:@"created"];

        [currentEntry writeToFile:file atomically:YES];

    }

}
return self;
}

- (void) setValue: (NSString *)value {
[currentEntry setObject:value forKey:@"location"];
}

- (NSString *) getValue {
return [currentEntry objectForKey:@"location"];
}


- (void) dealloc{
[currentEntry release];
[super dealloc];

}

@end

Если я инициализирую этот класс, он автоматически создаст словарь, и если я вызову один из методов set или get, кажется, что словарь сохраняется, так как он будет правильно освобожден.Если класс только что инициализирован, а затем методы не вызываются, он выдаст ошибки EXC_BAD_ACCESS.Если я не ошибаюсь, когда файл не существует, я неправильно инициализирую словарь, потому что метод начинается со словаря, а не с init.Хотя каждый раз, когда я запускаю этот файл, он всегда присутствует, поэтому он всегда использует логику найденного файла, и я подумал, что она сохранит переменную.

Не правильно ли я инициализирую словарь?

Редактировать- изменил код на удобный метод, чтобы отразить правильный путь.Все принимают к сведению то, что Скуги говорит.

Ответы [ 2 ]

2 голосов
/ 01 апреля 2011

Это плохо, плохо, плохо.

else {
        NSLog(@"file doesn't exist");
        currentEntry = [[NSMutableDictionary alloc ] dictionaryWithCapacity:1];

dictionaryWithCapacity: - это метод класса в NSMutableDictionary, который возвращает автоматически освобожденный объект, а вы не retain его. Таким образом, цикл выполнения заканчивается, и словарь автоматически освобождается. Затем вы запускаете [currentEntry release] в вашем dealloc, и он взрывается, потому что этот объект уже освобожден.

вы, вероятно, не хотите initWithCapacity: вместо этого. Всегда соединяйте alloc с методом, начинающимся с init.


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

- (id)init {
  // ...
  self.currentEntry = [NSMutableDictionary dictionWithContentsOfFile:file];
  // ...
}

- (void)dealloc {
  //...
  self.currentEntry = nil;
  //...
}

Таким образом, вам никогда не придется вызывать retain или release непосредственно на объекте. По моему опыту, это приводит к менее запутанным ошибкам. Но многие программисты ObjC также придерживаются стиля, с которым не все согласны.

0 голосов
/ 01 апреля 2011

Джошуа -

+ (id)dictionaryWithCapacity:(NSUInteger)numItems

- это метод класса NSDictionary.Поэтому, когда вы вызываете его, оно должно быть:

[NSMutableDictionary dictionaryWithCapacity:1];

Not:

[[NSMutableDictionary alloc] dictionaryWithCapacity:1];

Кроме того, [NSMutableDictionary dictionaryWithCapacity:] возвращает объект с автоматическим освобождением.Если вы хотите сохранить словарь в виде ивара и не иметь автоматического освобождения в следующем цикле цикла выполнения, вам следует вызвать:

[currentEntry retain];

Так что, в основном, измените его на:

currentEntry = [[NSMutableDictionary alloc] initWithCapacity:1];

или:

currentEntry = [[NSMutableDictionary dictionaryWithCapacity:1] retain];

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

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