object_getIvar の変数が基本データ型 (float、int、bool など) の場合、ドキュメントに従って関数がポインター (id) を返すため、値を取得するにはどうすればよいですか。int、int* にキャストしようとしましたが、それを NSLog に取得しようとすると、互換性のないポインター型に関するエラーが発生します。
5 に答える
取得:
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 の値を読み取ることができません。基本型 ivar を取得するには、object_getIvar の関数呼び出しをキャストする必要があります。
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
and BOOL
(ただし ではないfloat
) の場合、ポインターと int は同じサイズであり、互いにキャストできるため、ポインターをorにキャストできますint
。BOOL
(int)object_getIvar(obj, myIntVar)
おそらく、NSNumber の値をボックス化しています。これは、次のように、返された ID の className を NSLogging することで確認できます。
id returnedValue = object_getIvar(self, myIntVar);
NSLog(@"Class: %@", [returnedValue className]);
編集:ここでこのような別の質問を見つけました: object_getIvar(id object, 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;