2009-08-01 3 views
1

1) object_getIvar (id object, Ivar ivar) возвращает идентификатор, если Ivar является объектом, например. если variabe является NSString, предположительно id = NSString, который содержит значение. Это верно? Или что мне нужно сделать, чтобы получить доступ к значению Ивар.Обработка возвращаемого значения object_getIvar (id object, Ivar ivar)

2) если Ivar является float/int и т. Д., Что будет возвращено и как его преобразовать во что-то, что я могу использовать (float или int отлично, поскольку я могу использовать NSNumber numberWithXXX для преобразования его в объект).

ответ

1

1) Правильно. Как было указано в docs:

Возвращаемое значение
Значение переменной экземпляра определяется Ивар, или ноль, если объект является нулевым.

2) Независимо от типа Ivar вы всегда получите значение, которое имеет Ivar. Вы можете определить тип Ivar, используя ivar_getTypeEncoding. Существует список кодировок различного типа here.

С этой информацией вы должны иметь возможность написать переключатель, который обрабатывает каждый случай надлежащим образом; например .:

(предупреждение: не проверенный код впереди)

const char* typeEncoding = ivar_getTypeEncoding(var); 

switch (typeEncoding) { 
    case '@': { 
     // handle class case 
    } break; 

    case 'i': { 
     // handle int case 
    } break; 

    case 'f': { 
     // handle float case 
    } break; 

    // .. and so on 
} 
+3

Это не может надежно работать. Как возвращаются разные типы, зависит от ABI и не обязательно одинаково для всех типов. Я серьезно сомневаюсь, что это будет работать с структурами на x86, например. – Chuck

+2

@Chuck Документация не совсем понятна, но правильное использование - фактически нарисовать 'object_getIvar()' указателю функции, возвращающему правильный тип, подобный 'objc_msgSend()'. Например, для получения ivar 'CGRect' потребуется вызов типа CGRect rect = ((CGRect (*) (id, Ivar)) object_getIvar) (object, ivar)'. Затем компилятор выдает код с правильными соглашениями о вызовах. –

+1

Как ни странно, в Apple clang 4.1 все базовые типы (1, 2, 4 и 8 байтов с подписью и без знака) возвращаются, как ожидалось, ** кроме ** 32 и 64-битных чисел с плавающей запятой. Чтобы добраться до них, вы должны извлечь их, как если бы они были беззнаковыми 32 или 64-битными int и передали их соответствующему типу. Weird. –

0

Пример использования для печати описания произвольных объектов:

- (NSString *) qCustomDescription 
{ 
    static int depth = 0; 

    NSMutableString *resultString = [NSMutableString stringWithFormat: @"<%@: %p>", NSStringFromClass([self class]), self]; 

    uint32_t ivarCount; 
    Ivar *ivars = class_copyIvarList([self class], &ivarCount); 

    if(ivars) 
    { 
     ++depth; 
     [resultString appendString: @"\n"]; 

     for(int tabs = depth; --tabs > 0;) 
      [resultString appendString: @"\t"]; 

     [resultString appendString: @"{"]; 

     for(uint32_t i = 0; i < ivarCount; ++i) 
     { 
      Ivar ivar = ivars[i]; 
      const char* type = ivar_getTypeEncoding(ivar); 
      const char* ivarName = ivar_getName(ivar); 
      NSString* valueDescription = @""; 
      NSString* name = [NSString stringWithCString: ivarName encoding: NSASCIIStringEncoding]; 

      switch(type[0]) 
      { 
       case '@': 
       { 
        id v = object_getIvar(self, ivar); 
        if(v) 
        { 
         if([self respondsToSelector: @selector(qDescriptionForValue:)]) 
          valueDescription = [self performSelector: @selector(qDescriptionForValue:) withObject: v]; 
         else 
          valueDescription = [v description]; 
        } 
        break; 
       } 

       case 'c': 
       { 
        char v = ((char (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%c", v]; 
        break; 
       } 

       case 'i': 
       { 
        int v = ((int (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%i", v]; 
        break; 
       } 

       case 's': 
       { 
        short v = ((short (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%d", v]; 
        break; 
       } 

       case 'l': 
       { 
        long v = ((long (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%ld", v]; 
        break; 
       } 

       case 'q': 
       { 
        long long v = ((long long (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%lld", v]; 
        break; 
       } 

       case 'C': 
       { 
        unsigned char v = ((unsigned char (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%uc", v]; 
        break; 
       } 

       case 'I': 
       { 
        unsigned int v = ((unsigned int (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%u", v]; 
        break; 
       } 

       case 'S': 
       { 
        unsigned short v = ((unsigned short (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%u", v]; 
        break; 
       } 

       case 'L': 
       { 
        unsigned long v = ((unsigned long (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%lu", v]; 
        break; 
       } 

       case 'Q': 
       { 
        unsigned long long v = ((unsigned long long (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%llu", v]; 
        break; 
       } 

       case 'f': 
       { 
        float v = ((float (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%f", v]; 
        break; 
       } 

       case 'd': 
       { 
        double v = ((double (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%f", v]; 
        break; 
       } 

       case 'B': 
       { 
        BOOL v = ((BOOL (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%@", v ? @"YES" : @"NO"]; 
        break; 
       } 

       case '*': 
       { 
        char *v = ((char* (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"%s", v]; 
        break; 
       } 

       case '#': 
       { 
        id v = object_getIvar(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"Class: %s", object_getClassName(v)]; 
        break; 
       } 

       case ':': 
       { 
        SEL v = ((SEL (*)(id, Ivar))object_getIvar)(self, ivar); 
        valueDescription = [NSString stringWithFormat: @"Selector: %s", sel_getName(v)]; 
        break; 
       } 

       case '[': 
       case '{': 
       case '(': 
       case 'b': 
       case '^': 
       { 
        valueDescription = [NSString stringWithFormat: @"%s", type]; 
        break; 
       } 

       default: 
        valueDescription = [NSString stringWithFormat: @"UNKNOWN TYPE: %s", type]; 
        break; 
      } 

      [resultString appendString: @"\n"]; 

      for(int tabs = depth; --tabs >= 0;) 
       [resultString appendString: @"\t"]; 

      [resultString appendFormat: @"%@: %@", name, valueDescription]; 
     } 

     [resultString appendString: @"\n"]; 

     for(int tabs = depth; --tabs > 0;) 
      [resultString appendString: @"\t"]; 

     [resultString appendString: @"}"]; 
     --depth; 

     free(ivars); 
    } 

    return resultString; 
} 
Смежные вопросы