2011-06-16 17 views
9

ऑब्जेक्टिव-सी में, यह एक विधि है कि वस्तु आईडी और उदाहरण चर नाम/मान प्रिंट के साथ -description ओवरराइड करने के लिए आम बात है। मैं एक सामान्य -description विधि बनाना चाहता हूं जो इसे प्रत्येक वर्ग के लिए मैन्युअल रूप से करने के बजाय आत्मनिरीक्षण के माध्यम से करता है। मैं उत्पादन करना चाहते हैं होने के लिए कुछ की तरह:जेनेरिक ऑब्जेक्टिव-सी वर्णन इवर मुद्रित करने के लिए विधि को महत्व देता

<ClassName: 0x??????, ivar1: value1, ivar2: value2, ivar3: value3, ...> 

यह भी उदाहरण चर नाम से सॉर्ट करने के अच्छा होगा (ताकि वे एक ही क्रम में हमेशा से रहे हैं)। अंत में, यदि यह एक वर्ग को सुरक्षित रूप से NSObject कार्यक्षमता अधिभावी में डाल दिया जा सकता है, कि अधिक उचित होगा (लेकिन मुझे लगता है कि स्पष्ट नहीं है, के रूप में NSObject.m-description में -[NSString stringWithFormat:] उपयोग के बारे में एक चेतावनी है)।

उत्तर

12

यह एक अच्छा सवाल है! क्योंकि मुझे ऐसा कुछ नहीं मिला है, मैंने एक छोटा सा काम लिखा है जो आपके लिए यह करता है। यह NSObject विधि swizzling का उपयोग कर (हाँ, मैं इस बुराई कर रहा हूँ। MAHAHAHAHAHahahahaha) की - (NSString *)description बदल देता है और (आप इसे आसानी से संपादित उन्हें वर्णमाला के क्रम में प्रदर्शित करने के लिए कर सकते हैं) क्रम में वे भी वर्ग में प्रदर्शित में इवर प्रिंट करता है।

नहीं! NSObjectSwizzleDescription() पर कॉल करना भूल जाओ!

ज फ़ाइल:

@interface NSObject (JSObjectAdditions) 
@end 


void NSObjectSwizzleDescription(); 

मीटर फ़ाइल:

#import <objc/objc.h> 
#import "JSObject.h" 

@implementation NSObject (JSObjectAdditions) 

- (NSString *)verboseDescription 
{ 
    NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: %p>", NSStringFromClass([self class]), self]; 

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

    if(ivars) 
    { 
     [description appendString:@"\n{"]; 

     for(uint32_t i=0; i<ivarCount; i++) 
     { 
      Ivar ivar = ivars[i]; 
      const char *ivarType = ivar_getTypeEncoding(ivar); 
      id ivarObject = object_getIvar(self, ivar); 

      [description appendFormat:@"\n %s: ", ivar_getName(ivar)]; 

      // Default signed data types 
      if(strcmp(ivarType, "c") == 0) 
      { 
       char character = (char)ivarObject; 
       [description appendFormat:@"'%c'", character]; 
      } 
      else if(strcmp(ivarType, "i") == 0 || strcmp(ivarType, "l") == 0) // l is also 32 bit in the 64 bit runtime environment 
      { 
       int integer = (int)ivarObject; 
       [description appendFormat:@"%i", integer]; 
      } 
      else if(strcmp(ivarType, "s") == 0) 
      { 
       short shortVal = (short)ivarObject; 
       [description appendFormat:@"%i", (int)shortVal]; 
      } 
      else if(strcmp(ivarType, "q") == 0) 
      { 
       long long longVal = (long long)ivarObject; 
       [description appendFormat:@"%l", longVal]; 
      } 
      // Default unsigned data types 
      else if(strcmp(ivarType, "C") == 0) 
      { 
       unsigned char chracter = (unsigned char)ivarObject; 
       [description appendFormat:@"'%c'", chracter]; 
      } 
      else if(strcmp(ivarType, "I") == 0 || strcmp(ivarType, "L") == 0) 
      { 
       unsigned int integer = (unsigned int)ivarObject; 
       [description appendFormat:@"%u", integer]; 
      } 
      else if(strcmp(ivarType, "S") == 0) 
      { 
       unsigned short shortVal = (unsigned short)ivarObject; 
       [description appendFormat:@"%i", (int)shortVal]; 
      } 
      else if(strcmp(ivarType, "Q") == 0) 
      { 
       unsigned long long longVal = (unsigned long long)ivarObject; 
       [description appendFormat:@"%ll", longVal]; 
      } 
      // Floats'n'stuff 
      else if(strcmp(ivarType, "f") == 0) 
      { 
       float floatVal; 
       memcpy(&floatVal, &ivarObject, sizeof(float)); 

       [description appendFormat:@"%f", floatVal]; 
      } 
      else if(strcmp(ivarType, "d") == 0) 
      { 
       double doubleVal; 
       memcpy(&doubleVal, &ivarObject, sizeof(double)); 

       [description appendFormat:@"%f", doubleVal]; 
      } 
      // Boolean and pointer 
      else if(strcmp(ivarType, "B") == 0) 
      { 
       BOOL booleanVal = (BOOL)ivarObject; 
       [description appendFormat:@"%@", (booleanVal ? @"YES" : @"NO")]; 
      } 
      else if(strcmp(ivarType, "v") == 0) 
      { 
       void *pointer = (void *)ivarObject; 
       [description appendFormat:@"%p", pointer]; 
      } 
      else if(strcmp(ivarType, "*") == 0 || strcmp(ivarType, ":") == 0) // SEL is just a typecast for a cstring 
      { 
       char *cstring = (char *)ivarObject; 
       [description appendFormat:@"\"%s\"", cstring]; 
      } 
      else if(strncmp(ivarType, "@", 1) == 0) 
      { 
       [description appendFormat:@"%@", ivarObject]; 
      } 
      else if(strcmp(ivarType, "#") == 0) 
      { 
       Class objcClass = (Class)ivarObject; 
       [description appendFormat:@"%s", class_getName(objcClass)]; 
      } 
      else 
       [description appendString:@"???"]; 
     } 

     [description appendString:@"\n}"]; 
     free(ivars); 
    } 

    return description; 
} 

@end 


void NSObjectSwizzleDescription() 
{ 
    Method origMethod = class_getInstanceMethod([NSObject class], @selector(description)); 
    Method newMethod = class_getInstanceMethod([NSObject class], @selector(verboseDescription)); 

    method_exchangeImplementations(origMethod, newMethod); 
} 
+0

शब्द के लिए +1 "swizzling" – jrdioko

+0

+1 और भयानक। सभी स्ट्रिंग्स को 'एनएसएमयूटेबलएरे' में जोड़ना और '[सरणी घटकोंजॉन्डेडब्रिंगिंग: @ ""]' लौटाना, आवंटन को सहेजकर थोड़ा सा प्रदर्शन बेहतर करेगा, हालांकि एनएसएमयूटेबलस्ट्रिंग का 'एपेंडफॉर्मैट' * नहीं * ओ (एन^2) 'है, इसलिए यह नहीं है महत्वपूर्ण। – orip

1

मैं यह कर किसी भी कोड पता नहीं है, लेकिन यह है कि अगर मौजूद है, मैं डीबगिंग उद्देश्यों के लिए दिलचस्पी होगी!

मुझे आश्चर्य है कि मुझे ऐसा कुछ नहीं मिला, classic techniques बस काम करता है, लेकिन वास्तव में यह अच्छा होगा कि inspect विधि, जो मुझे लगता है, प्रतिबिंब का उपयोग करके संभव है, लेकिन शायद मैं ' मैं गलत हूं।

मैं एक नज़र a this interesting post है, जो आप के लिए क्या देख रहे से संबंधित है देने के लिए सुझाव है, और इसे लागू करने के लिए एक आधार हो सकता है।

एक और दिलचस्प बात यह है कि जो डिबगिंग के लिए एक अच्छा उपकरण है, यह भी NSLogger है।