Object_getInstanceVariable يعمل مع Float ، int ، Bool ، ولكن ليس للمضاعفة؟

StackOverflow https://stackoverflow.com/questions/1219081

سؤال

لدي object_getInstanceVariable للعمل كما هنا ومع ذلك ، يبدو أنه يعمل فقط من أجل العوامات والملحوم و ints لا تتضاعف. أظن أنني أفعل شيئًا خاطئًا ولكني كنت أذهب في دوائر مع هذا.

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.2f, ، لا تتغير القيمة عندما أقرأها بعد object_getInstanceVariable مكالمة. ضبط myIntValue لبعض القيمة الأخرى قبل getinstancevar وظيفة أعلاه إرجاع 2 كما ينبغي ، أي. تم تغييره.

ثم حاولت

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

إذا فعلت ivar_getName(tmpIvar) أحصل على "يومًا ما" ، لكن myDoubuleValue = 0 ساكن! ثم أحاول ivar_getTypeEncoding(tmpIvar) وأحصل على "D" كما ينبغي.

لتلخيص ، إذا typeEncoding = float, إنه يعمل ، إذا كان مزدوجًا ، فسيتم تعيين النتيجة ولكنه يقرأ بشكل صحيح المتغير وقيمة الإرجاع (IVAR) صحيحة أيضًا.

يجب أن أفعل شيئًا أساسيًا لا أستطيع رؤيته ، لذا أقدر إذا تمكن شخص ما من الإشارة إليه.

هل كانت مفيدة؟

المحلول

object_getInstanceVariable هي وظيفة صغيرة مشوشة. إنها موثق أن المعلمة الأخيرة هي أ void ** المعلمة - أي أنك تمر بعنوان أ void * متغير واحصل على مؤشر إلى متغير المثيل - ولكن يتم تنفيذه كما لو كان void * المعلمة - أي أنك تمرر عنوان المتغير الذي تريد الاحتفاظ بنسخة من متغير المثيل. المشكلة هي أن التنفيذ يتجاهل حجم متغير المثيل ويقوم فقط بنسخة مؤشر. لذلك أي شيء بنفس حجم المؤشر سيعمل بشكل مثالي. إذا كنت تعمل على بنية 32 بت ، فسيتم نسخ 32 بت فقط. (يجب أن تشهد نفس السلوك مع long long متغير مثيل كذلك.)

الحل هو استخدام واجهة برمجة التطبيقات الأولية ، ترميز القيمة الرئيسية, ، استخدام -valueForKey:.

الحل الآخر: إذا أردت كتابة نسخة ثابتة ، قل كفئة لـ 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"];

نصائح أخرى

ماذا عن استخدام valueforkey:؟

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

ملاحظة: هذا يتطلب منك أن يكون لديك طريقة "SomeFloat". إذا كنت ترغب في استخدام setValue: forkey: ، ستحتاج أيضًا إلى "metsomefloat:" الطريقة. يتم تنفيذ ذلك بسهولة عن طريق إعلان IVAR باعتباره property وتوليفه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top