Ich habe eine Funktion, die CFTypeRef zurückgibt. Ich habe keine Ahnung, was es wirklich ist. Wie kann ich das feststellen? Zum Beispiel könnte es ein CFStringRef sein.
Die kurze Antwort ist, dass Sie das können (siehe Dave DeLongs Antwort). Die lange Antwort ist, dass Sie nicht können. Beide sind wahr. Eine bessere Frage könnte sein: "Warum musst du es wissen?" Meiner Meinung nach, wenn Sie Dinge arrangieren können, so dass Sie nicht wissen müssen, werden Sie wahrscheinlich besser dran sein.
Ich sage nicht, dass Sie es nicht tun können, oder auch nicht. Was ich sage ist, dass es einige verborgene Probleme gibt, wenn Sie diesen Pfad beginnen, und manchmal sind Sie sich nicht wirklich bewusst, was all die unausgesprochenen Annahmen sind. Leider hängt die Programmierung richtig davon ab, alle kleinen Details zu kennen. Aus der Spitze meines Kopfes, hier sind ein paar der möglichen Fallstricke:
Nach meinem besten Wissen ist die Anzahl der Core Foundation-Typen in jeder größeren OS-Version gestiegen. Daher enthält jede Haupt-OS-Version einen Superset-Core-Foundation-Typ der vorherigen Versionen und wahrscheinlich eine strenge Obermenge. Dies ist "beobachtetes Verhalten" und nicht notwendigerweise "garantiertes" Verhalten. Es ist wichtig zu beachten, dass "Dinge sich ändern können" und dass alle Dinge gleich sind, die leichteren und einfacheren Lösungen dazu neigen, dies nicht zu berücksichtigen. Es wird allgemein als schlechter Programmierstil angesehen, etwas zu programmieren, das in der Zukunft bricht, unabhängig von dem Grund oder der Begründung.
Wegen der gebührenfreien Überbrückung zwischen Core Foundation und Foundation, nur weil ein CFTypeRef = CFStringRef
nicht bedeutet, dass CFTypeRef ≡ CFStringRef
ist, wobei =
"gleich" bedeutet und ≡
"identisch mit" bedeutet. Es gibt eine Unterscheidung, die je nach Kontext wichtig sein kann oder auch nicht. Als Warnung ist dies die Stelle, an der sich die Käfer frei bewegen.
Zum Beispiel kann ein CFMutableStringRef
verwendet werden, wo immer ein CFStringRef
verwendet werden kann, oder CFStringRef = CFMutableStringRef
. Sie können jedoch nicht CFStringRef
verwenden, wenn ein CFMutableStringRef
aus offensichtlichen Gründen verwendet werden kann. Das bedeutet CFStringRef ≢ CFMutableStringRef
. Wiederum können sie je nach Kontext gleich sein, aber sie sind nicht identisch.
Es ist sehr wichtig zu beachten, dass es zwar ein CFStringGetTypeID()
gibt, aber kein entsprechendes CFMutableStringGetTypeID()
.
Logischerweise ist CFMutableStringRef
eine strenge Obermenge von CFStringRef
. Es würde dann folgen, dass das Übergeben eines echten unveränderlichen CFStringRef
zu einem CFMutableString
API-Aufruf "irgendeine Art von Problem" verursachen würde. Auch wenn dies jetzt nicht wahr ist (z. B. 10.6), weiß ich in der Vergangenheit, dass das Folgende in der Vergangenheit wahr war: Die CFMutableString
API-Aufrufe haben nicht verifiziert, dass "das String-Argument" tatsächlich änderbar ist (das war tatsächlich wahr) für alle Typen, die zwischen unveränderlich und veränderlich unterschieden). Die Überprüfungen waren da, aber sie waren in Form von Debug-Assertions, die bei "Release" -Builds deaktiviert waren (mit anderen Worten, die Überprüfungen wurden in der Praxis nie durchgeführt).
Dies ist (oder wurde möglicherweise) offiziell nicht als Fehler angesehen, und die ( trivialen ) Mutabilitätsprüfungen wurden aus Leistungsgründen nicht durchgeführt . Es wird keine "öffentliche" API bereitgestellt, um die Änderbarkeit eines CFString
-Zeigers (oder der Veränderlichkeit eines beliebigen Typs) mitzuteilen. In Kombination mit gebührenfreiem Bridging bedeutete dies, dass Sie immutable NSString
-Objekte mutieren konnten, obwohl die NSMutableString
APIs eine Mutabilitätsprüfung durchgeführt und "ein Problem" verursacht hatten, als Sie versuchten, ein unveränderliches Objekt zu mutieren. Flavor mit der Tatsache, dass @""
konstante Zeichenfolgen in Ihrer Quelle zur Laufzeit dem schreibgeschützten Speicher zugeordnet sind.
Die offizielle Zeile war, wie ich mich erinnere, "unveränderliche Objekte, entweder CFStringRef oder NSString, nicht an CFMutableString APIs zu übergeben, und außerdem war es ein Fehler, dies zu tun". Als es darauf hingewiesen wurde, dass es mit dieser Haltung einige sicherheitsrelevante Probleme geben könnte (ganz egal, dass es grundsätzlich unmöglich war), sagen wir, wenn jemals etwas den Fehler gemacht hätte, kritisch von der Unveränderlichkeit einer Saite zu sprechen, besonders "bekannt" Strings, die Antwort war "das Problem ist theoretisch und nichts wird in dieser Zeit getan werden, bis ein praktikabler Exploit demonstriert werden kann."
Update: Ich war gespannt auf das aktuelle Verhalten. Auf meinem Rechner läuft 10.6.4, indem CFMutableString
APIs auf einem unveränderlichen CFString
verwendet werden, was dazu führt, dass der unveränderliche String im Wesentlichen @""
wird, was mindestens besser ist als vorher (& lt; = 10.5) und tatsächlich mutiert die Saite. Definitiv nicht die ideale Lösung, hat diese bittere reale Welt Geschmack, wo seine einzige erlösende Qualität ist, dass es "die am wenigsten schlechteste Lösung" ist.
Also denke daran, sei vorsichtig in deinen Annahmen! Sie können es tun, aber wenn Sie das tun, ist es wichtiger, dass Sie nicht falsch tun. :) Natürlich werden viele "falsche" Lösungen funktionieren, daher ist die Tatsache, dass die Dinge funktionieren, nicht unbedingt ein Beweis dafür, dass Sie es richtig machen. Gute Zeiten!
Auch in einem Duck Typed -System wird es oft als schlechte Form und möglicherweise sogar als Fehler angesehen, "nachzusehen" zu eng bei der Art eines Objekts ".Objective-C ist definitiv ein Ducktyp-System, das aufgrund der engen Kopplung der gebührenfreien Überbrückung zweifellos in Core Foundation übergeht. CFTypeRef
ist eine direkte Manifestation dieser Ducktyp-Ambiguität und kann, abhängig vom Kontext, eine explizite Art sein zu sagen: "Du solltest nicht zu genau auf die Typen schauen".
Wenn Sie herausfinden möchten, welchen Typ ein CFTypeRef
während der Entwicklung hat, können Sie das folgende Snippet verwenden.
Dies wird einen lesbaren Namen für den Typ ausgeben, damit Sie wissen, was es ist. Aber Apple übernimmt keine Garantie dafür, dass diese Beschreibungen konsistent bleiben, also verwenden Sie diese nicht im Produktionscode. (Wie auch immer, das Snippet wird Speicher verlieren, aber Sie sollten es nur während der Entwicklung verwenden, also wen kümmert es).
Tags und Links objective-c core-foundation