Цель c, утечка памяти, чтение из sqlite и присвоение значений NSDictionary и NSAarray - PullRequest
0 голосов
/ 09 января 2010

У меня есть список магазинов в файле ListController. Я установил базу данных sqlite, в которой храню 60 магазинов. В верхней части списка у меня есть панель поиска.

Я создал класс DataController, который отвечает за загрузку и хранение данных в БД.

@interface DataController : NSObject {
 sqlite3 *database;
 NSArray *shops;    
 NSDictionary* dictionaryOfShops;
}

@property (nonatomic, retain) NSDictionary *dictionaryOfShops;
@property (nonatomic, retain) NSArray* shops;
-(void)initializeShops;

метод initializeShops загружает данные из базы данных и сохраняет результаты в 2 подпорках следующим образом:

-(void)initializeShops{
    [dictionaryOfShops release];
    [shops release];

    NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];

    if (sqlite3_open(....))
    NSString *query = ....
    if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) ==   SQLITE_OK) 
    {
        while (sqlite3_step(statement) == SQLITE_ROW) {

           int rId = sqlite3_column_int(statement, 0);
           char *rName = (char *)sqlite3_column_text(statement, 1);

           Shop* s  = [[Shop alloc] init];
           s.ID = rId;
           if(sName != nil) s.Name = [NSString stringWithUTF8String:rName];

               NSString *shopID = [[NSString alloc] initWithFormat:@"%d",s.ID];
           [dictionary setObject:s forKey:shopID];
           [shopID release];
           [s release];         
        }
        sqlite3_finalize(statement);
    }
    [query release];

    dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
    shops =    [[NSArray alloc] initWithArray:[dictionary allValues]];

    dictionary = nil;
    [dictionary release];

       //Sorting
       NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
    NSArray *sortedList =[self.shops sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
    self.shops = sortedList; 
    [sort release];
}

Проблема в том, что когда пользователь вводит какой-то текст в поиск На панели я изменяю значение запроса (добавляя LIKE ....), а затем снова вызываю метод initializeShops. Этот второй раз делает так много утечек, (связанных со свойствами класса Shop) и Утечки также NSDictionary и NSArray.

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

Я принимаю любое предложение, так как я действительно застрял на нем.

MORE

Действительно странная вещь - это управление памятью моего словаря var, а также магазинов с двумя реквизитами и dictionaryOfShops. С этим кодом

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//add data to dictionary 
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops =    [[NSArray alloc] initWithArray:[dictionary allValues]];
[dictionary release]

Учитывая, что dictionaryOfShops и shop - это два синтезированных свойства (nonatomic, retain), как я могу изменить их значение без утечек?

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

Ответы [ 3 ]

2 голосов
/ 09 января 2010

Первый вопрос Почему бы просто не использовать базовые данные? Скорее всего, это будет быстрее, потребует меньше кода и будет значительно легче поддерживать со временем. Быть тупым; SQLite обманчиво сложен. Легко начать, исключительно трудно получить право.

В любом случае, управление памятью dictionary неверно. Это не сбой, потому что вы поменяли порядок назначения и выпуска nil, как предложил kennyTM. Я бы предложил , а не создать автоматически выпущенный словарь.

В противном случае написанный код кажется на первый взгляд довольно непроницаемым. Итак:

  1. Можете ли вы предоставить еще немного кода? Что-нибудь интересное в памяти происходит в другом месте?

  2. Вы используете многопоточность вообще (или NSOperationQueue)

  3. Вы бежали под утечками инструмент и извлек следы выделения какие объекты просочились?

1 голос
/ 09 января 2010
dictionary = nil;
[dictionary release];

Пожалуйста, поменяйте местами эти 2 утверждения. В этой форме это означает [nil release], который является неактивным.

0 голосов
/ 10 января 2010

Хорошо, я нашел ошибку. В моем классе Shop я понимаю, что не реализовал метод

 -(void)dealloc

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

...