2009-09-22 13 views
7

Angenommen, Sie haben eine Methode, die eine neu generierte NSArray-Instanz zurückgibt, die intern mit einem NSMutableArray erstellt wird. Haben Sie immer etwas tun:Wie vorsichtig sind Sie mit Ihren Rückgabetypen in Objective-C?

- (NSArray *)someArray { 
    NSMutableArray *mutableArray = [[NSMutableArray new] autorelease]; 
    // do stuff... 
    return [NSArray arrayWithArray:mutableArray]; // .. or [[mutableArray copy] autorelease] 
} 

Oder lassen Sie nur die änderbaren Array-Objekt, wie sie ist und es direkt zurück, weil NSMutableArray eine Unterklasse von NSArray ist:

- (NSArray *)someArray { 
    NSMutableArray *mutableArray = [[NSMutableArray new] autorelease]; 
    // do stuff... 
    return mutableArray; 
} 

Ich persönlich oft Verwandle ein veränderbares Array in ein NSArray, wenn ich von solchen Methoden zurückkomme, nur weil ich es irgendwie "sicherer" oder "korrekter" finde. Obwohl ich ehrlich gesagt kein Problem damit hatte, ein veränderbares Array zurückzuschicken, das in ein NSArray umgewandelt wurde, ist es in der Realität wahrscheinlich kein Problem - aber gibt es eine Best Practice für solche Situationen?

Antwort

9

Ich habe die return [NSArray arrayWithArray:someMutableArray] gemacht, aber ich war langsam überzeugt, dass es keinen wirklichen Vorteil bietet. Wenn ein Aufrufer Ihrer API ein zurückgegebenes Objekt als Unterklasse der deklarierten Klasse behandelt, tun sie es falsch.

[NB:. Unten BBUM der Vorbehalt] Siehe

+1

stimme ich generell zu. Wenn jedoch die Möglichkeit besteht, dass der aufrufende Code mit dem zurückgegebenen Wert herumfummelt, kann dies ernsthafte Probleme verursachen, dann ist eine defensive Kopie eine gute Idee. Dies gilt insbesondere für den Framework-Code. –

+0

Wenn der aufrufende Code etwas mutiert, was Ihre API als unveränderlich behandelt, sollten sie eine "-mutableCopy" machen. Sonst mache ich es falsch. ;) (Nichts hindert Sie daran, defensiv zu sein, wenn Sie das Gefühl haben müssen.) – Wevah

+4

Das eigentliche Problem besteht jedoch darin, dass der Aufrufer, der ein NSArray * erhält, einen veränderbaren Array-Verweis auf ein Array zurückgeben kann, das später mutiert werden kann gehe davon aus, dass sich der Inhalt nie ändert ... und ... naja ... * BOOM *. – bbum

5

Es ist sehr üblich, einen NSMutableArray-Cast als NSArray zurückzugeben. Ich denke, die meisten Programmierer würden erkennen, dass sie, wenn sie ein unveränderliches Objekt niederwerfen und es mutieren, böse Bugs einführen werden.

Auch wenn Sie eine NSMutableArray-IVAR someMutableArray haben, und Sie [NSArray arrayWithArray:someMutableArray] in einer KVC-Accessor-Methode zurückgeben, kann es KVO durcheinander bringen. Sie werden damit beginnen, dass "Objekt wurde mit zugeordneten Beobachtern noch zugeordnet" -Fehler.

0

NSArray ist in der Tat ein Klassencluster, kein Typ, wie auch immer. Wo auch immer Sie ein NSArray sehen, ist es wahrscheinlich sowieso einer von mehreren verschiedenen Typen. Daher ist das "Konvertieren zu NSArray" etwas irreführend; Ein NSMutableArray entspricht bereits der NSArray-Schnittstelle, und darum werden sich die meisten kümmern.

CocoaObjects fundamentals

In jedem Fall gegeben, dass Sie ein Array sind Rückkehr (und es danach nicht mehr zu halten, dank der Autorelease) müssen Sie wahrscheinlich keine Sorgen machen, ob das Array wandelbar ist oder nicht.

Wenn Sie jedoch das Array beibehalten, möchten Sie dies möglicherweise tun, um zu verhindern, dass die Clients den Inhalt ändern.

+1

Es ist kein NSArray Protokoll. NSMutableArray ist eine Unterklasse der NSArray-Klasse. –

+0

Peter, Sie haben absolut Recht, es war ein Fehler meinerseits - bedeutete "Schnittstelle" dort. Ich habe meine Antwort entsprechend aktualisiert. – AlBlue

Verwandte Themen