2009-08-01 7 views

risposta

6

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

+2

Questo non funziona perché hai avuto un refuso, se cambi (void) e myFloatValue in (void *) e myFloatValue funziona come pubblicizzato. –

+0

Accidenti, hai ragione :) – jhauberg

+0

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. –

-1

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.

+0

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? –

+0

@Russel Sto esaminando e sperimentando. Modificherò la mia risposta se capisco qualcosa. –

+0

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. –

-1

è 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; 
+0

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 .... –

+0

okay l'ho cambiato per usare void *. provalo ora – newacct

+0

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. –

2

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) 
+0

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. –

3

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)