13

私はここでobject_getInstanceVariable仕事をしなければなりませんが、それはフロート、ブール、イントでのみ機能し、ダブルでは機能しないようです。私は何か間違ったことをしているのではないかと思いますが、私はこれと輪になって行ってきました。

float myFloatValue;
float someFloat = 2.123f;
object_getInstanceVariable(self, "someFloat", (void*)&myFloatValue);

動作し、myFloatValue = 2.123

でもやってみると

double myDoubleValue;
double someDouble = 2.123f;
object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);

取得しmyDoubleValue = 0ます。関数の前に設定しようとするとmyDoubleValue、たとえば。double myDoubleValue = 1.2fobject_getInstanceVariable呼び出し後に読んだときの値は変わりません。myIntValue上記の関数の前に他の値に設定するとgetinstancevar、2が返されます。変更されました。

それから私は試しました

Ivar tmpIvar = object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);

私がそうするならば、私はivar_getName(tmpIvar)「someDouble」を手に入れます、しかしmyDoubuleValue = 0それでも!それから私は試しivar_getTypeEncoding(tmpIvar)てみて、あるべき「d」を取得します。

要約するとtypeEncoding = float、が機能する場合、それがdoubleの場合、結果は設定されませんが、変数を正しく読み取り、戻り値(Ivar)も正しいです。

私は私が見ることができない基本的な間違ったことをしているに違いないので、誰かがそれを指摘してくれれば幸いです。

4

2 に答える 2

30

object_getInstanceVariable混乱した小さな関数です。最後のパラメーターはパラメーターであることが文書化void **されています。つまり、変数のアドレスを渡し、void *インスタンス変数へのポインターを取得しますが、void *パラメーターであるかのように実装されます。つまり、インスタンス変数のコピーを保持する変数。問題は、実装がインスタンス変数のサイズを無視し、ポインタコピーを実行することです。したがって、ポインタと同じサイズのものはすべて完全に機能します。32ビットアーキテクチャで実行している場合は、上位32ビットのみがコピーされます。long long(インスタンス変数でも同じ動作を確認する必要があります。)

解決策は、を使用して、プライマリAPIであるキー値コーディングを使用すること-valueForKey:です。

もう1つの解決策:たとえばNSObjectのカテゴリとして固定バージョンを作成する場合は、次のようになります。

@implementation NSObject (InstanceVariableForKey)

- (void *)instanceVariableForKey:(NSString *)aKey {
    if (aKey) {
        Ivar ivar = object_getInstanceVariable(self, [aKey UTF8String], NULL);
        if (ivar) {
            return (void *)((char *)self + ivar_getOffset(ivar));
        }
    }
    return NULL;
}

@end

その場合、コードは次のようになります。

double myDoubleValue = *(double *)[self instanceVariableForKey:@"someDouble"];
于 2009-08-02T21:43:59.863 に答える
2

valueForKeyの使用についてはどうですか?

NSNumber * value = [self valueForKey:[NSString stringWithUTF8String:ivar_getName(tmpIvar)]];
NSLog(@"Double value: %f", [value doubleValue];

注:これには、「someFloat」メソッドが必要です。setValue:forKey:を使用する場合は、「setSomeFloat:」メソッドも必要です。これは、ivarを@propertyとして宣言し、それを合成することで簡単に実装できます。

于 2009-08-02T17:00:21.793 に答える