Objective-C: fissaggio gestione della memoria in un metodo

voti
5

Ho quasi non capire una gestione semplice conteggio dei riferimenti / memoria in Objective-C, ma sto avendo un momento difficile con il seguente codice. Sto rilasciando mutableDict (commentato nel seguente codice) e sta causando un comportamento dannoso nel mio codice. Se lascio la perdita di memoria, funziona come previsto, ma non è chiaramente la risposta qui. ;-) Qualcuno di voi gente più esperti essere così gentile da puntare nella giusta direzione per quanto come posso riscrivere qualsiasi di questo metodo per gestire meglio la mia occupazione di memoria di me? Soprattutto per come sto riuscendo NSMutableDictionary * mutableDict, come quello è il grande colpevole qui. Mi piacerebbe capire il problema, e non basta copiare / incollare il codice - così alcuni commenti / feedback è l'ideale. Ringrazia tutti.

- (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;
}
È pubblicato 26/02/2009 alle 23:32
fonte dall'utente
In altre lingue...                            


3 risposte

voti
5

Ecco un riscrittura equivalente del codice:

- (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;
}

Notate che ho fatto solo riferimento contando su theXMLDocument. Questo perché gli array e dizionari vivono oltre la portata di questo metodo. L' arraye dictionarymetodi della classe creare istanze di autoreleased NSArraye NSMutableDictionaryoggetti. Se il chiamante non li conserva in modo esplicito, saranno rilasciati automaticamente al prossimo go-round del ciclo di eventi dell'applicazione.

  • Ho anche rimosso il codice che non è mai sta per essere giustiziato. Il CXMLNode namemetodo dice che restituisce una stringa, in modo che prova sarà sempre vero.
  • Se mutableDictè nil, si hanno grossi problemi. E 'meglio che viene generata un'eccezione di fallire in modo silenzioso, così ho fatto via con quel test, anche.
  • Ho anche usato la relativamente nuova forsintassi di enumerazione, che elimina le variabili contatore.
  • Ho rinominato alcune variabili e il metodo di essere un po 'più di cacao-ish. Il cacao è diverso dalla maggior parte delle lingue nel senso che è generalmente considerato non corretto per usare un verbo come "creare" a meno che non specificatamente vuole fare il chiamante responsabile del rilascio qualsiasi oggetto si torna.
  • Non hai fatto niente con theError. Si dovrebbe neanche controllare e segnalare l'errore, oppure passare nilse non avete intenzione di controllarlo. Non c'è alcun senso nel fare app costruire un oggetto di errore non avete intenzione di utilizzare.

Spero che questo aiuta farti puntato nella giusta direzione.

Risposto il 27/02/2009 a 00:18
fonte dall'utente

voti
1

Beh, rilasciando mutableDict in realtà non dovrebbe causare alcun problema, perché la linea di sopra di essa (l'aggiunta di mutableDict a mutableArray) manterrà automaticamente. Mentre io non sono sicuro di cosa esattamente sta andando male con il codice (non ha specificato quali "cose ​​cattive" si intendono), ci sono alcune cose generali vorrei suggerire:

  1. Non autorelease mutableArray subito. Che sia una dichiarazione regolare alloc / init e autorelease quando si ritorna in esso ( "ritorno [mutableArray autorelease];").

  2. theXMLDocument perde, assicurarsi di rilasciare che prima di tornare. Inoltre, non c'è bisogno di conservarlo come siete. alloc / init fa il lavoro avviando l'oggetto trattenere conteggio a 1, mantenendo nuovamente solo assicura che perde sempre. Sbarazzarsi del trattenere e rilasciare prima di tornare e non colerà.

  3. Solo un consiglio: essere sicuri di conservare il valore di ritorno di questo metodo quando si utilizza altrove - il risultato è stato autoreleased come non è garantito di essere in giro quando ne avete bisogno a meno che non esplicitamente mantenere / release da qualche parte.

In caso contrario, questo codice dovrebbe funzionare. Se non lo fa ancora, un'altra cosa che vorrei provare è forse facendo [mutableArray addObject: [mutableDict copiare]] per garantire che si mutableDict non causa problemi quando viene rilasciato.

Risposto il 26/02/2009 a 23:49
fonte dall'utente

voti
0

In Memory Management Guida alla programmazione in tema Tornando oggetti dai metodi (scorrere verso il basso un po '), ci sono alcuni semplici esempi su come restituire gli oggetti da un metodo con il managment di memoria corretta.

Risposto il 08/09/2010 a 22:48
fonte dall'utente

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