2009-08-01 9 views
7

object_getIvarの変数が基本データ型(float、int、boolなど)の場合はどうすれば関数として値を取得できますかドキュメントに従ってポインタ(id)を返します。 int、int *にキャストしようとしましたが、NSLogを取得しようとすると、互換性のないポインタ型についてエラーが発生します。object_getIvar(self、myIntVar)のint値をポインタを返すようにするにはどうすればいいですか?

答えて

6

を取得します:

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

出力:ARC用

2.340000

+2

(void)&myFloatValueを(void *)&myFloatValueに変更した場合は、誤ってタイプミスが発生しました。 –

+0

まあ、そうだよ:) – jhauberg

+0

floatのobject_setInstanceVariableのアイデアは?私はそれを介してintのために働くことができます int myInt = 5; int theInt; object_setInstanceVairable(self、 "theInt"、(void *)myInt); ポインタとintが同じサイズであるため、浮動小数点数では機能しません。 –

-1

おそらくNSNumberのボクシング値です。

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

編集:あなたはそうのように、返されたIDのクラス名をNSLoggingことによってこれを確認することができ、私はちょうどここにこのような別の質問が見つかりました:私自身の実験からHandling the return value of object_getIvar(id object, Ivar ivar)

を、それは私のオリジナルの仮定ように思われます間違っていたintおよびfloatなどのプリミティブが実際の値として返されるように見えます。しかし、ivar_getTypeEncodingを使用して、返される値が期待している型であることを検証することが適切です。

+0

私は[returnedValueクラス名]を呼び出すしようとすると、クラス名が見つからないという警告が表示されます。私は次に、object_getClassName(object_getIvar(self、myIntVar))を使用してみました(myIntVarはforループで実際に割り当てられているため変更されています)、ループは一度実行され、GDBで終了します。ログに記録される唯一の値は「無」です...アイデアですか? –

+0

@Russel私はそれを調べて実験しています。私が何かを理解するなら、私の答えを編集します。 –

+0

Jacobはobject_getInstanceVariableを使って動作させましたが、明らかに高速であるため、object_getIvarを動作させる方法についてはまだ不思議です(http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html #// apple_ref/c/func/object_getIvar)ネットを使用してサンプルを検索しようとしましたが、誰も基本タイプで使用していないようです。 –

-1

あなたは直接object_getInstanceVariableを使用することができます(それをテストしていない)

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

私は3番目の引数に互換性のないポインタ時間を取得....私はひどくObj-Cに精通していない私は恐れています。ドキュメントは、それは私が思うのと同じthatsのvoidポインタでなければならないと言う?その場合、私は上記と同じ問題に戻ります。 –

+0

大丈夫です。void *を使うように変更しました。今すぐ試してください – newacct

+0

最後の行でGDBにメッセージが出て、なぜ警告なしでコンパイルされますか?私がその行で続けると、メモリ管理に関連していると思う「EXC_BAD_ACCESS」が表示されます。それ以上の考え?ところで、私はこれを行う前に私のvar typeEncoding = "f"をチェックしていますので、変数/メモリ割り当てなどの不一致が原因ではありません。 –

2

返される値は、オブジェクト内の適切な場所からの値です。ちょうど正しいタイプではありません。ポインタとint型のサイズが同じであるため、intBOOL(ただしfloat)のために、あなただけの、intまたはBOOLへのポインタを唱えられると、彼らはお互いにキャストすることができます。

(int)object_getIvar(obj, myIntVar) 
+0

しかし、これは動作するようです....私はboolとintを扱うためにtypeEncodingのケースを使うことができますが、私はまだ解決策を探しています。 –

3

この答えに触発さ:object_getIvar fails to read the value of BOOL iVar。 基本タイプのivarsを取​​得するには、object_getIvarの関数呼び出しをキャストする必要があります。基本的なタイプのためにあなたがマクロの呼び出し(のparams例えばを指定する必要があり、その後

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

:私は、このような関数ポインタの高速な定義のための小さな便利なマクロを作った

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

(長い長い、LONGLONGは))に適合します:

GET_IVAR_OF_TYPE_DEFININTION(int, Int) 

その後int型(または指定を受けるための機能)変数の型が利用可能になる:

int result = XYIntGetVariableFunction(object, variableName) 
関連する問題