se la variabile in object_getIvar è un tipo di dati di base (ad esempio float, int, bool) come si ottiene il valore come funzione restituisce un puntatore (id) in base alla documentazione. Ho provato a trasmettere su int, int * ma quando provo a farlo su NSLog, ottengo un errore su un tipo di puntatore incompatibile.Come ottengo il valore int da object_getIvar (self, myIntVar) poiché restituisce un puntatore
risposta
Getting:
myFloat = 2.34f;
float myFloatValue;
object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue);
NSLog(@"%f", myFloatValue);
Uscite:
2,340000
Impostazione:
float newValue = 2.34f;
unsigned int addr = (unsigned int)&newValue;
object_setInstanceVariable(self, "myFloat", *(float**)addr);
NSLog(@"%f", myFloat);
Uscite:
2,340000
Probabilmente sta inserendo il valore in un NSNumber. È possibile verificare ciò NSLogging className del id restituito, in questo modo:
id returnedValue = object_getIvar(self, myIntVar);
NSLog(@"Class: %@", [returnedValue className]);
Edit: ho trovato un'altra domanda proprio come questo qui: Handling the return value of object_getIvar(id object, Ivar ivar)
Dalla mia sperimentazione, sembrerebbe che la mia ipotesi iniziale era sbagliato int e float e altri primitivi sembrano essere restituiti come valore effettivo. Tuttavia, sarebbe opportuno utilizzare ivar_getTypeEncoding per verificare che il valore restituito sia il tipo che si aspetta che sia.
quando provo a chiamare [returnedValue className], Ricevo avviso nessun metodo className trovato. Ho quindi provato a utilizzare object_getClassName (object_getIvar (self, myIntVar)) (myIntVar viene effettivamente allocato in un ciclo for in modo che cambi) e il ciclo viene eseguito una volta e quindi finisco in GDB ma non viene registrato alcun errore. L'unico valore che viene registrato è 'nil' ... idee? –
@Russel Sto esaminando e sperimentando. Modificherò la mia risposta se capisco qualcosa. –
Jacob ha funzionato usando object_getInstanceVariable ma sono ancora curioso di sapere come far funzionare object_getIvar perché è apparentemente più veloce (http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html # // apple_ref/c/func/object_getIvar) Ho provato a cercare in rete esempi che lo usassero, ma nessuno sembra usarlo con i tipi di base. –
è possibile utilizzare direttamente object_getInstanceVariable
: (non hanno provato)
void *ptr_to_result;
object_getInstanceVariable(obj, "intvarname", &ptr_to_result);
float result = *(float *)ptr_to_result;
Ricevo tempo di puntatore incompatibile sul terzo argomento .... Non ho molta familiarità con Obj-C, ho paura. i documenti dicono che dovrebbe essere un puntatore vuoto, questo è lo stesso di id che penso? nel qual caso sono tornato allo stesso problema di cui sopra .... –
okay l'ho cambiato per usare void *. provalo ora – newacct
ora esce su GDB nell'ultima riga senza alcun messaggio sul motivo, tuttavia compila senza avvisi. Se premo continuare su questa riga, ottengo "EXC_BAD_ACCESS" che penso sia correlato alla gestione della memoria. Qualche altra idea? A proposito, controllo che il mio var typeEncoding = "f" prima di fare questo non può essere dovuto alla mancata corrispondenza delle variabili/allocazione di memoria ecc. Almeno non lo penso. –
Il valore restituito è il valore dal posto giusto nell'oggetto; solo non il tipo giusto. Per int
e BOOL
(ma non float
), si può solo il cast del puntatore a un int
o BOOL
, dal momento che i puntatori e interi sono le stesse dimensioni e possono essere lanciati gli uni agli altri:
(int)object_getIvar(obj, myIntVar)
sembra funzionare comunque .... Posso usare un caso sul typeEncoding per gestire i bool e gli ints ma per i float sto ancora cercando una soluzione. –
Per ARC:
Ispirato da questa risposta: object_getIvar fails to read the value of BOOL iVar. È necessario eseguire una chiamata di funzione per object_getIvar per ottenere ivars di tipo base.
typedef int (*XYIntGetVariableFunction)(id object, const char* variableName);
XYIntGetVariableFunction intVariableFunction = (XYIntGetVariableFunction)object_getIvar;
int result = intVariableFunction(object, intVarName);
ho fatto un piccolo macro utile per una rapida definizione di tali puntatori a funzione:
#define GET_IVAR_OF_TYPE_DEFININTION(type, capitalized_type) \
typedef type (*XY ## capitalized_type ## GetVariableFunctionType)(id object, Ivar ivar); \
XY ## capitalized_type ## GetVariableFunctionType XY ## capitalized_type ## GetVariableFunction = (XY ## capitalized_type ## GetVariableFunctionType)object_getIvar;
Poi, per i tipi di base è necessario specificare le chiamate a macro (per esempio params(Lunga lunga, LONGLONG) si adatta):
GET_IVAR_OF_TYPE_DEFININTION(int, Int)
E dopo che una funzione per la ricezione int (o specificato) tipo di variabile diventano disponibili:
int result = XYIntGetVariableFunction(object, variableName)
Questo non funziona perché hai avuto un refuso, se cambi (void) e myFloatValue in (void *) e myFloatValue funziona come pubblicizzato. –
Accidenti, hai ragione :) – jhauberg
Qualche idea per object_setInstanceVariable per un float? Posso farlo funzionare per un int tramite int myInt = 5; int theInt; object_setInstanceVairable (self, "theInt", (void *) myInt); perché i puntatori e gli int sono della stessa dimensione, quindi non funziona per i float. –