2009-08-01 12 views

Respuesta

6

Conseguir:

myFloat = 2.34f; 

float myFloatValue; 
object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue); 

NSLog(@"%f", myFloatValue); 

Salidas:

2,340000

Configuración:

float newValue = 2.34f; 
unsigned int addr = (unsigned int)&newValue; 

object_setInstanceVariable(self, "myFloat", *(float**)addr); 

NSLog(@"%f", myFloat); 

Salidas:

2,340000

+2

Eso no funciona porque tienes un error tipográfico, si cambias (nulo) y myFloatValue a (void *) & myFloatValue funciona como se anuncia. –

+0

Maldición, tienes razón :) – jhauberg

+0

¿Alguna idea para object_setInstanceVariable for a float? Puedo hacer que funcione para una int a través de int myInt = 5; int theInt; object_setInstanceVairable (self, "theInt", (void *) myInt); porque los punteros y las entradas son del mismo tamaño, por lo que no funciona para flotadores. –

-1

Es probable que encapsule el valor en un NSNumber. Usted puede verificar esto NSLogging className del ID devuelto, así:

id returnedValue = object_getIvar(self, myIntVar); 
NSLog(@"Class: %@", [returnedValue className]); 

Editar: me encontré con otra pregunta como ésta aquí: Handling the return value of object_getIvar(id object, Ivar ivar)

Desde mi propia experimentación, parecería que mi suposición original, era incorrecto. int y float y otras primitivas parecen devolverse como el valor real. Sin embargo, sería apropiado utilizar ivar_getTypeEncoding para verificar que el valor devuelto sea del tipo que espera que sea.

+0

cuando intento llamar [returnedValue className], Me aparece una advertencia: no se ha encontrado el método className. Luego intenté usar object_getClassName (object_getIvar (self, myIntVar)) (myIntVar está realmente asignado en un bucle for para que cambie) y el bucle se ejecuta una vez y luego termino en GDB pero no hay ningún error registrado. El único valor que se registra es 'nil' ... ¿ideas? –

+0

@Russel Estoy investigando y experimentando. Editaré mi respuesta si descubro algo. –

+0

Jacob lo hizo funcionar usando object_getInstanceVariable, pero todavía tengo curiosidad sobre cómo hacer que object_getIvar funcione porque aparentemente es más rápido (http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html # // apple_ref/c/func/object_getIvar) Intenté buscar en la red ejemplos que lo usaran pero nadie parece usarlo con tipos básicos. –

-1

puede utilizar directamente object_getInstanceVariable: (no lo he probado)

void *ptr_to_result; 
object_getInstanceVariable(obj, "intvarname", &ptr_to_result); 
float result = *(float *)ptr_to_result; 
+0

Obtengo un tiempo de puntero incompatible en el tercer argumento ... No estoy muy familiarizado con Obj-C, me temo. los documentos dicen que debería ser un puntero vacío, eso es lo mismo que id, ¿no? en cuyo caso estoy de vuelta al mismo problema que el anterior .... –

+0

bien lo cambié para usar void *. pruébelo ahora – newacct

+0

ahora sale a GDB en la última línea sin ningún mensaje de por qué, sin embargo compila sin advertencias. Si presiono continuar en esa línea, obtengo 'EXC_BAD_ACCESS', que creo que está relacionado con la administración de la memoria. ¿Alguna idea adicional? Por cierto, compruebo que mi var typeEncoding = "f" antes de hacer esto no puede deberse a una falta de coincidencia de variables/asignación de memoria, etc. Al menos no lo creo. –

2

El valor que se devuelve es el valor desde el lugar correcto en el objeto; simplemente no es del tipo correcto. Para int y BOOL (pero no float), sólo podría emitir el puntero a un int o BOOL, ya que los punteros y enteros son del mismo tamaño y que se puede lanzar el uno al otro:

(int)object_getIvar(obj, myIntVar) 
+0

esto parece funcionar sin embargo ... puedo usar un caso en typeEncoding para manejar los bools y los ints pero para los flotadores todavía estoy buscando una solución. –

3

Para ARC:

Inspirado por esta respuesta: object_getIvar fails to read the value of BOOL iVar. Tiene que invocar la llamada de función para object_getIvar para obtener ivars de tipo básico.

typedef int (*XYIntGetVariableFunction)(id object, const char* variableName); 
XYIntGetVariableFunction intVariableFunction = (XYIntGetVariableFunction)object_getIvar; 
int result = intVariableFunction(object, intVarName); 

he hecho una pequeña macro útil para una rápida definición de dichos punteros de función:

#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; 

Entonces, para los tipos básicos que necesita para especificar las llamadas a la macro (por ejemplo, params(Largo, largo, Longlong) encajará):

GET_IVAR_OF_TYPE_DEFININTION(int, Int) 

Y después de que una función para recibir int (o especificado) tipo de variable que se disponga:

int result = XYIntGetVariableFunction(object, variableName) 
Cuestiones relacionadas