Cocoa: Testen, ob ein NSString unveränderlich oder veränderbar ist?

7

Dies erzeugt ein unveränderliches String-Objekt:

%Vor%

Dies erzeugt ein veränderbares String-Objekt:

%Vor%

Aber beide Objekte werden als die gleiche Art von Objekt gemeldet, "NSCFString":

%Vor%

Was unterscheidet diese Objekte also intern, und wie teste ich das, damit ich leicht feststellen kann, ob eine Mystery-String-Variable unveränderlich oder veränderlich ist, bevor ich etwas Böses dazu tue?

    
StringSection 19.01.2010, 10:08
quelle

3 Antworten

12

In den Dokumenten finden Sie eine ziemlich lange Erklärung, warum Apple dies nicht möchte und warum sie das nicht explizit in Mutable Objekte erhalten . Die Zusammenfassung ist:

  

Also treffen Sie keine Entscheidung über das Objekt   Veränderlichkeit basierend auf welcher Introspektion   sagt dir etwas über ein Objekt. Behandeln   Objekte als veränderbar oder nicht basierend auf   was Sie in der API erhalten   Grenzen (das heißt, basierend auf dem   Rückgabetyp). Wenn du musst   Markieren Sie ein Objekt eindeutig als   veränderlich oder unveränderlich, wenn Sie es übergeben   an Kunden, geben Sie diese Informationen als ein   zusammen mit dem Objekt markieren.

Ich finde ihr NSView-Beispiel am einfachsten zu verstehen, und es veranschaulicht ein grundlegendes Cocoa-Problem. Sie haben ein NSMutableArray mit dem Namen "elements", das Sie als Array bereitstellen möchten, aber nicht möchten, dass Anrufer sich darum kümmern. Sie haben mehrere Möglichkeiten:

  1. Setzen Sie Ihr NSMutableArray als NSArray frei.
  2. Erstellen Sie immer eine nicht veränderbare Kopie, wenn Sie dazu aufgefordert werden
  3. Speichern Sie Elemente als NSArray und erstellen Sie bei jeder Mutation ein neues Array.

Ich habe all das an verschiedenen Punkten gemacht. # 1 ist bei weitem die einfachste und schnellste Lösung. Es ist auch gefährlich, da das Array hinter dem Rücken des Anrufers mutieren könnte. Aber Apple gibt in einigen Fällen an, was sie tun (beachten Sie die Warnung für - Unterviews in NSView). Ich kann bestätigen, dass, während # 2 und # 3 viel sicherer sind, sie große Leistungsprobleme verursachen können, weshalb Apple sich entschieden hat, sie nicht für häufig verwendete Mitglieder wie -subviews zu verwenden.

Das Ergebnis von all dem ist, dass, wenn du # 1 benutzt, die Introspektion dich in die Irre führen wird. Sie haben eine NSMutableArray-Darstellung als NSArray, und die Introspektion zeigt an, dass sie veränderbar ist (Introspektion hat keine Möglichkeit, etwas anderes zu erfahren). Aber du darfst es nicht mutieren. Das kann nur die Überprüfung der Kompilierzeit sagen, und das ist das Einzige, dem Sie vertrauen können.

Der Fix hierfür wäre eine Art von unveränderbarer Fast Copy-on-Write-Version einer veränderbaren Datenstruktur. Auf diese Weise könnte # 2 möglicherweise mit anständiger Leistung durchgeführt werden. Ich kann mir vorstellen, dass Änderungen am NSArray-Cluster dies erlauben würden, aber es existiert heute in Cocoa nicht (und könnte die NSArray-Leistung im Normalfall beeinträchtigen, was es zu einem Nicht-Starter macht). Selbst wenn wir es hatten, gibt es wahrscheinlich zu viel Code da draußen, der darauf angewiesen ist, dass das aktuelle Verhalten Mutabilität introspektion immer zutraut.

    
Rob Napier 19.01.2010 15:48
quelle
4

Es gibt keine (dokumentierte) Möglichkeit festzustellen, ob eine Zeichenfolge zur Laufzeit veränderbar ist oder nicht.

Sie würden erwarten, dass einer der folgenden Schritte funktioniert, aber keiner von ihnen funktioniert:

%Vor%

Weitere Informationen hier, obwohl es Ihnen mit dem Problem nicht hilft:

Ссылка

    
Philippe Leybaert 19.01.2010 10:12
quelle
3

Wenn Sie nach Debugging-Zwecken suchen möchten, sollte der folgende Code funktionieren. Kopieren auf unveränderliche Objekt ist selbst, während es eine echte Kopie für veränderbare Typen ist, das ist, worauf der Code basiert. Beachten Sie, dass es, da es copy aufruft, langsam ist, aber zum Debuggen in Ordnung sein sollte. Wenn Sie nach anderen Gründen als dem Debuggen suchen möchten, sehen Sie Rob an (und vergessen Sie es).

%Vor%

Haftungsausschluss: Natürlich gibt es keine Garantie dafür, dass Kopie für unveränderliche Typen gleichwertig ist. Sie können sicher sein, dass, wenn isMutable NO zurückgibt, es nicht änderbar ist, also sollte die Funktion wahrscheinlich canBeMutable heißen. In der realen Welt ist es jedoch eine ziemlich sichere Annahme, dass unveränderliche Typen (NSString, NSArray) diese Optimierung implementieren. Es gibt eine Menge Code out einschließlich grundlegende Dinge wie NSDictionary, die schnelle Kopie von unveränderlichen Typen erwartet.

    
mfazekas 19.01.2010 12:37
quelle