Как получить значение int из object_getIvar(self, myIntVar), поскольку оно возвращает указатель
-
07-07-2019 - |
Вопрос
если переменная в object_getIvar имеет базовый тип данных (например.float, int, bool) как мне получить значение, поскольку функция возвращает указатель (id) согласно документации.Я пробовал выполнить приведение к int, int*, но когда я пытаюсь передать это в NSLog, я получаю сообщение об ошибке о несовместимом типе указателя.
Решение
Получающий:
myFloat = 2.34f;
float myFloatValue;
object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue);
NSLog(@"%f", myFloatValue);
Выходы:
2.340000
Параметр:
float newValue = 2.34f;
unsigned int addr = (unsigned int)&newValue;
object_setInstanceVariable(self, "myFloat", *(float**)addr);
NSLog(@"%f", myFloat);
Выходы:
2.340000
Другие советы
Для ARC:
Вдохновленный этим ответом: object_getIvar не удается прочитать значение BOOL iVar . Вы должны вызвать вызов функции для object_getIvar, чтобы получить ivars базового типа.
typedef int (*XYIntGetVariableFunction)(id object, const char* variableName);
XYIntGetVariableFunction intVariableFunction = (XYIntGetVariableFunction)object_getIvar;
int result = intVariableFunction(object, intVarName);
Я сделал небольшой полезный макрос для быстрого определения таких указателей на функции:
#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;
Затем для базовых типов необходимо указать обращения к макросу (например, параметры (long long, LongLong) подойдут):
GET_IVAR_OF_TYPE_DEFININTION(int, Int)
И после этого становится доступной функция для получения типа переменной int (или указанного):
int result = XYIntGetVariableFunction(object, variableName)
Возвращаемое значение - это значение из правильного места в объекте; просто не тот тип. Для int
и BOOL
(но не float
) вы можете просто привести указатель к int
или BOOL
, поскольку указатели и целые числа имеют одинаковый размер и их можно приводить друг к другу:
(int)object_getIvar(obj, myIntVar)
Это, вероятно, бокс в значении в NSNumber. Вы можете проверить это с помощью NSLogging возвращенного идентификатора className, например, так:
id returnedValue = object_getIvar(self, myIntVar);
NSLog(@"Class: %@", [returnedValue className]);
Изменить: я нашел еще один вопрос, такой же, как этот, здесь: Обработка возвращаемого значения object_getIvar (объект id, Ivar ivar) р>
Из моих собственных экспериментов оказалось, что мое первоначальное предположение было неверным. int и float и другие примитивы, по-видимому, возвращаются как фактические значения. Однако было бы целесообразно использовать ivar_getTypeEncoding, чтобы убедиться, что возвращаемое значение соответствует ожидаемому типу.
вы можете использовать object_getInstanceVariable
напрямую: (еще не проверял)
void *ptr_to_result;
object_getInstanceVariable(obj, "intvarname", &ptr_to_result);
float result = *(float *)ptr_to_result;