Ich wollte eine Reihe von Rechtecken mit entsprechenden Aktionen verknüpfen, also habe ich es versucht
%Vor%aber ich bekomme den Fehler "Initialisierungselement ist nicht konstant". Gibt es einen Grund dafür, dass das, was ich versuche zu tun, generell nicht erlaubt ist oder im globalen Rahmen nicht erlaubt ist, oder habe ich einen kleinen Satzfehler?
Diese Antwort gibt an, warum "initializer element is not constant"
.
Gegeben das folgende Beispiel:
%Vor% Kompiliert zu so etwas für die i386
-Architektur:
Dieser Teil definiert zwei lokale (in Bezug auf den Assembly-Code) "Variablen" (tatsächlich Labels), L_OBJC_METH_VAR_NAME_4
und L_OBJC_SELECTOR_REFERENCES_5
. Der Text .objc_meth_var_names
und .objc_message_refs
, kurz vor den Variablenvariablen, teilt dem Assembler mit, in welchen Abschnitt der Objektdatei "das Folgende" eingefügt werden soll. Die Abschnitte sind für den Linker sinnvoll. L_OBJC_SELECTOR_REFERENCES_5
wird anfänglich auf die Adresse von L_OBJC_METH_VAR_NAME_4
gesetzt.
Zum Ausführungsladezeitpunkt, bevor das Programm ausgeführt wird, führt der Linker etwas wie folgt aus:
.objc_message_refs
Abschnitt. 0
terminated C
string. L_OBJC_METH_VAR_NAME_4
, die
enthält die Zeichenfolge ASCII
C
"constantSelector:test:"
. sel_registerName("constantSelector:test:")
nicht wörtlich heißen. Im Wesentlichen führt der Linker dies zur Ladezeit für unser Beispiel aus:
%Vor% Deshalb muss das Der ... wird zu: Da der Linker seine gesamte Arbeit vor der Ausführung des Programms erledigt, enthält Der Unterschied besteht darin, dass es sich um einen Funktionsaufruf handelt. Die Funktion muss die eigentliche Arbeit zum Auffinden des Selektors ausführen, wenn sie bereits registriert wurde, oder sie muss einen neuen Alle Selektoren müssen Jetzt weißt du es. Und Wissen ist die halbe Miete! L_OBJC_SELECTOR_REFERENCES_5
- das Initialisierungselement zur Kompilierungszeit konstant sein. Der Wert ist erst bekannt, wenn das Programm ausgeführt wird. Auch dann werden Ihre sel_registerName()
-Deklarationen in einem anderen Linker-Abschnitt gespeichert, dem "initializer element is not constant"
-Abschnitt. Der Linker weiß nur, wie er struct
-Werte im Abschnitt .data
aktualisiert, und es gibt keine Möglichkeit, den berechneten SEL
-Wert von .objc_message_refs
an eine beliebige Stelle in SEL
. .objc_message_refs
Quellcode ... .data
den genau gleichen Wert, den Sie erhalten würden, wenn Sie C
: L_OBJC_SELECTOR_REFERENCES_5
Wert zuweisen, um den Selektor zu registrieren. Dies ist wesentlich langsamer als das Laden eines konstanten Wertes. Obwohl dies "langsamer" ist, können Sie eine beliebige sel_registerName("constantSelector:test:")
-Zeichenfolge übergeben. Dies kann nützlich sein, wenn:
SEL
bekannt. C
durchlaufen, wodurch jedes sel_registerName()
genau einmal registriert wird. Dies hat den Vorteil, dass für jeden gegebenen Selektor überall genau ein Wert vorhanden ist. Obwohl ein privates Detail der Implementierung, ist sel_registerName()
"normalerweise" nur ein SEL
-Zeiger auf eine Kopie der Selektoren SEL
string text.
Wie wäre es mit:
%Vor%Registrieren Sie zur Laufzeit die Selektoren:
%Vor%Ausgabe:
%Vor% Weitere Informationen zu sel_registerName()
finden Sie unter Objective-C 2.0-Laufzeitreferenz .
Sieht aus, als erfindest du NSCell hier neu. Wenn Sie ein Menü implementieren möchten, warum verwenden Sie keine vorhandenen UI-Klassen?
Tags und Links objective-c iphone selector