Die Dokumentation enthält eine ziemlich lange Erklärung, warum Apple dies nicht möchte und warum sie dies explizit in Receiving Mutable Objects nicht unterstützt. Die Zusammenfassung ist:
So stellen keine Entscheidung über Objekt Veränderlichkeit basiert auf, was Selbstbeobachtung informiert Sie über ein Objekt. Behandeln Sie Objekte als veränderbar oder nicht basierend auf , was Sie in der API Grenzen (das heißt, basierend auf der Rückgabetyp) übergeben werden. Wenn Sie ein Objekt eindeutig als veränderlich oder unveränderlich markieren müssen, wenn Sie es an Clients übergeben, übergeben Sie diese Information als Flag zusammen mit dem Objekt.
Ich finde ihre 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 Optionen:
- Legen Sie Ihr NSMutableArray als NSArray offen.
- Erstellen Sie immer eine nicht veränderbare Kopie, wenn Sie dazu aufgefordert werden
- Speichern Sie Elemente als NSArray und erstellen Sie jedes Mal ein neues Array, wenn es mutiert.
Ich habe all diese an verschiedenen Punkten getan. # 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 -subviews 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 Sie # 1 verwenden, die Introspektion Sie 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. Nur die Kompilierzeitprüfung kann Ihnen das sagen, und das ist das einzige, dem Sie vertrauen können.
Der Fix für diese wäre eine Art schnelle Kopie-auf-schreiben unveränderliche 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 hätten, gibt es wahrscheinlich zu viel Code, der darauf angewiesen ist, dass das aktuelle Verhalten Mutabilität introspizieren kann.
Philippe-Code von - if ([myStringB isKindOfClass: [NSMutableString-Klasse]]) - funktioniert und löst das praktische Problem. – StringSection
Ich bin immer noch neugierig darauf, wie der Unterschied zwischen einer unveränderlichen und veränderbaren Zeichenkette intern dargestellt wird, und ob das direkt erkannt werden kann (die tatsächliche "Objektart", die mit NSLog gedruckt wird). – StringSection
Korrektur: Ich habe mich geirrt, der Code - if ([myStringB isKindOfClass: [NSMutableString Klasse]]) - funktioniert schließlich nicht. Es gibt True zurück, ob die Zeichenfolge NSString oder NSMutableString ist. Wie Philippe unten anführt (in seiner nun editierten Antwort mit anderem Code), gibt es offenbar keine dokumentierte Möglichkeit, veränderbare gegen unveränderliche Objekte zur Laufzeit allgemein zu erkennen. – StringSection