2009-06-10 7 views
2

ich dieses Problem mit Cocoa, ich bin eine Funktion und Ein Array es ruft:NSMutableArray in eine Funktion übergeben

Einige wo ich die Funktion aufrufen:

[self processLabels:labels]; 

und die Funktion als folgen:

- (void)processLabels:(NSMutableArray*)labs{ 
    labs = [[NSMutableArray alloc] init]; 
    [labs addObject:@"Random"]; 
.... 
} 

beim Debuggen, merke ich, dass kein neues Objekt an Etiketten werden hinzugefügt, wenn sie zu den Labors hinzugefügt werden. Liegt es daran, dass ich Labore neu initialisiere? Wie könnte ich dann Etiketten innerhalb der Funktion neu initialisieren?

Ich habe versucht, mithilfe von byref nicht gelungen, jede Hilfe ist willkommen .. dank

Antwort

1

Die Anweisung labs = [[NSMutableArray alloc] init]; macht labs, um im Rahmen der Methode auf das neue Array zu zeigen. Der Zeiger des Aufrufers zeigt nicht auf das neue Array.

Wenn Sie den Anrufer Zeiger ändern möchten, tun Sie etwas wie folgt aus:

// The caller 
NSMutableArray *labels;   // Don't initialize *labels. 
[self processLabels:&labels]; 

... 

- (void)processLabels:(NSMutableArray**)labs{ 
    *labs = [[NSMutableArray alloc] init]; 
    [*labs addObject:@"Random"]; 
    ... 
} 

Das ist wahrscheinlich eine schlechte Idee, weil processLabels: das Array reserviert, aber der Anrufer ist verantwortlich für befreien.

Wenn Sie den Anrufer wollen das Array besitzen, könnten Sie processLabels: so schreiben:

- (void)processLabels:(NSMutableArray*)labs{ 
    [labs removeAllObjects]; 
    [labs addObject:@"Random"]; 
    ... 
} 

Oder, wenn processLabels: ist nur eine Sammlung von Etiketten Rückkehr:

- (NSMutableArray*)processLabels { 
    NSMutableArray* labs = [[[NSMutableArray alloc] init] autorelease]; 
    [labs addObject:@"Random"]; 
    ... 
    return labs; 
} 

Wenn Sie möchten, Der Anrufer, der für die Freigabe des Arrays verantwortlich ist, entfernt die Autorelease. In diesem Fall schreibt die Konvention vor, dass der Methodenname mit alloc oder new beginnt oder das Wort copy enthält.

3

‚Labs‘ initialisiert werden sollten, bevor Sie es zu processLabels passieren, und dann sollte es nicht neu initialisiert werden .

Wenn Sie nicht das Array initialisieren vorher aus irgendeinem Grund, und Sie wollen processLabels es zu erstellen, benötigen Sie einen Zeiger auf einen Zeiger weitergeben müssen:

[self processLabels:&labels]; 

und das Verfahren würde sich ändern:

- (void)processLabels:(NSMutableArray**)labs{ 
    *labs = [[NSMutableArray alloc] init]; 
    [*labs addObject:@"Random"]; 
.... 
} 
1

Sie müssen in einer änderbaren Array passieren kann, um es ändern (das ist die Definition von mutable) - eine NSArray in eine änderbare Array zu drehen, zu verwenden:

NSMutableArray *writableArray = [NSMutableArray arrayWithArray:oldArray]; 

oder wenn Sie nur eine leere änderbare Array machen wollen.

NSMutableArray *writableArray = [NSMutableArray array]; 

Dann passieren, dass in

2

allgemein gesprochen, ist es preferrable nicht wandelbar Sammlungen passieren, aber Methoden zu schaffen, die Arbeit zu verrichten auf sie ...

in der Tat frage ich mich als Antwort auf Ihren Code sogar, was der Zweck ist, die "Labs" -Array in die Funktion zu übergeben, wenn Sie tatsächlich nur es überschreiben (und ein Speicherleck in der verarbeiten). warum das tun?

+0

Ich stimme dir zu. Wenn Sie eine ungültige Rückgabe haben, warum nicht einfach das Array zurückgeben? – Abizern

1

Will ist richtig, sowohl über die Korrektur der bestehenden Methode, und darüber, dass es eine schlechte Idee ist. Die Speicherung auf einem By-Reference-Parameter ist sicherlich gültig und wird häufig in reinen C-Programmen verwendet, aber in diesem Fall wird unnötige Komplexität hinzugefügt. In Objective-C ist es das bevorzugte Idiom, Objekte mit dem Rückgabewert zuerst zurückzugeben und nur dann zurück zu einem Zeiger zu speichern, wenn der Rückgabewert bereits verwendet wird, um etwas anderes zurückzugeben. Dies wird nicht nur dazu führen, dass Aufrufe einer Methode einfacher zu lesen und zu schreiben sind, sondern entspricht auch Standard-Idiomen, die häufig in anderen Sprachen verwendet werden (z. B. Java und C#). Es wird ziemlich offensichtlich, wenn Sie einen Array-Zeiger überschreiben, indem Sie ihm einen potenziellen Fehler zuweisen, der eher von Tools wie dem Clang Static Analyzer erkannt wird.

Zu einem verwandten Hinweis sollten Sie wahrscheinlich auch eine bessere Benennung von Methoden und Parametern in Betracht ziehen. (Ich weiß, dass dies wahrscheinlich ein etwas erfundenes Beispiel ist.) Wenn Sie "Labels" verarbeiten und sie von einer anderen Quelle als dem veränderbaren Array kommen, das Sie erstellen, würde ich die lokale Variable "Labs" oder "Labs" nicht nennen. Labels "- verwenden Sie einen aussagekräftigeren Namen. Methodennamen, die weniger vage über ihre Vorgehensweise sind, können die Lesbarkeit von Codes erheblich verbessern. In Objective-C werden lange beschreibende Methodennamen bevorzugt. Da Xcode die Codevervollständigung durchführt und die Methodennamen weniger eindeutig sind, ist das Endergebnis normalerweise weniger Typisierung.

Verwandte Themen