Objective-C: Крепление управления памятью в методе

голоса
5

Я почти там понимание простого управления подсчетом ссылок / памяти в Objective-C, но у меня трудное время с помощью следующего кода. Я выпускаю mutableDict (с комментариями в коде ниже), и это вызывает пагубное поведение в моем коде. Если я позволяю утечку памяти, он работает, как ожидалось, но это явно не ответ здесь. ;-) Будут ли какие-либо из вас более опытных людей любезно указать мне в правильном направлении, как я могу переписать любого из этого метода, чтобы лучше справиться с моим объемом памяти? В основном с тем, как я управляющий NSMutableDictionary * mutableDict, так как это большой преступник здесь. Я хотел бы понять проблему, а не просто копировать / вставить код - поэтому некоторые комментарии / обратная связь является идеальной. Спасибо всем.

- (NSArray *)createArrayWithDictionaries:(NSString *)xmlDocument 
                               withXPath:(NSString *)XPathStr {

    NSError *theError = nil;
    NSMutableArray *mutableArray = [[[NSMutableArray alloc] init] autorelease];
    //NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
    CXMLDocument *theXMLDocument = [[[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError] retain]; 
    NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];
    int i, j, cnt = [nodes count];
    for(i=0; i < cnt; i++) {
        CXMLElement *xmlElement = [nodes objectAtIndex:i];
        if(nil != xmlElement) {
            NSArray *attributes = [NSArray array];
            attributes = [xmlElement attributes];
            int attrCnt = [attributes count];
            NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
            for(j = 0; j < attrCnt; j++) {
                if([[[attributes objectAtIndex:j] name] isKindOfClass:[NSString class]]) 
                    [mutableDict setValue:[[attributes objectAtIndex:j] stringValue] forKey:[[attributes objectAtIndex:j] name]];
                else 
                    continue;
            }
            if(nil != mutableDict) {
                [mutableArray addObject:mutableDict];
            }
            [mutableDict release];  // This is causing bad things to happen.
        }
    }

    return (NSArray *)mutableArray;
}
Задан 26/02/2009 в 23:32
источник пользователем
На других языках...                            


3 ответов

голоса
5

Вот эквивалент переписывание кода:

- (NSArray *)attributeDictionaries:(NSString *)xmlDocument withXPath:(NSString *)XPathStr {
    NSError *theError = nil;
    NSMutableArray *dictionaries = [NSMutableArray array];
    CXMLDocument *theXMLDocument = [[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError]; 
    NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];

    for (CXMLElement *xmlElement in nodes) {
        NSArray *attributes = [xmlElement attributes];
        NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
        for (CXMLNode *attribute in attributes) {
            [attributeDictionary setObject:[attribute stringValue] forKey:[attribute name]];
        }

        [dictionaries addObject:attributeDictionary];
    }

    [theXMLDocument release];
    return attributeDictionaries;
}

Заметьте , что я только сделал подсчет ссылок на theXMLDocument. Это потому , что массивы и словари живут за рамки этого метода. arrayИ dictionaryметоды класса создание autoreleased экземпляров NSArrayи NSMutableDictionaryобъектов. Если абонент не явно сохранить их, они будут автоматически освобождены на следующей карусели из цикла событий приложения.

  • Я также удалил код , который никогда не собирается быть казнен. CXMLNode nameМетод говорит , что он возвращает строку, так что тест всегда будет истинным.
  • Если mutableDictесть nil, у вас есть большие проблемы. Это лучше , что он бросает исключение , чем молча терпят неудачу, так что я покончила с этим испытанием, тоже.
  • Я также использовал относительно новый forсинтаксис перечисления, который делает прочь с встречным переменными.
  • Я переименовал некоторые переменные и метод, чтобы быть немного больше какао-иш. Какао отличается от большинства языков в том, что это обычно считается неправильным использовать глагол как «создать», если вы специально не хотите, чтобы вызывающий абонент отвечает за освобождение любого объекта вы вернетесь.
  • Ты ничего с не делать theError. Вы должны либо проверить его и сообщить об ошибке, либо передать , nilесли вы не собираетесь , чтобы проверить это. Там нет смысла в создании приложения построить объект ошибки , вы не собираетесь использовать.

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

Ответил 27/02/2009 в 00:18
источник пользователем

голоса
1

Ну, высвобождая mutableDict действительно не должны вызывать никаких проблем, потому что линия над ней (добавление mutableDict к mutableArray) сохранит его автоматически. Хотя я не уверен, что именно происходит не так с вашим кодом (вы не указали, что «плохие вещи» означает), есть несколько общих вещей, которые я хотел бы предложить:

  1. Не autorelease mutableArray сразу. Пусть это будет регулярное заявление Alloc / инициализации и autorelease, когда вы возвращаете его ( «возвращение [mutableArray autorelease];»).

  2. theXMLDocument подтекает, убедитесь, что освободить перед возвратом. Кроме того, вам не нужно, чтобы сохранить его, как вы. Alloc / инициализации выполняет работу, начиная объект сохранить счетчик на 1, сохранив его снова только гарантирует, что утечки навсегда. Избавиться от сохранить и освободить его, прежде чем вернуться, и это не будет течь.

  3. Просто совет: убедитесь, что вы сохранить возвращаемое значение этого метода при использовании его в другом месте - результат был autoreleased как не гарантируется, чтобы быть вокруг, когда вам это нужно, если вы явно не сохранить / выпустить его где-нибудь.

В противном случае, этот код должен работать. Если он все еще не делает, одна вещь , которую я хотел бы попробовать это , возможно , делает [mutableArray AddObject: [mutableDict копировать]] , чтобы гарантировать , что mutableDict не вызывает у вас никаких проблем , когда он будет выпущен.

Ответил 26/02/2009 в 23:49
источник пользователем

голоса
0

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

Ответил 08/09/2010 в 22:48
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more