Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSObject description and custom summaries in Xcode

I override object's -(NSString*)description however Xcode always displays error: summary string parsing error in summary field in variables view.

My current implementation is the following:

- (NSString*)description {
    return [NSString stringWithFormat:@"<%@ %p> x=%f, y=%f", self.class, self, _x, _y];
}

If I type po objectName in console, LLDB shows a fine output as expected, however Xcode and command p objectName always indicate error, so what's the proper debug description format to make summary field work? Worth to notice that the output of "p" command is the same as a summary message that you see in Xcode for instances of Foundation classes.

Update:

As far as I can see from "WWDC 2012 session Debugging in Xcode", custom summaries can be implemented using Custom python script only. -(NSString*)description or -(NSString*)debugDescription methods are not connected anyhow to summary messages. I thought they are because I got an error displayed, but it seems it's a standard message for classes that do not have their own formatters.

like image 438
Rob Zombie Avatar asked Aug 06 '13 21:08

Rob Zombie


1 Answers

I would suggest at least:

- (NSString*)description {
    return [NSString stringWithFormat:@"%@; x=%f, y=%f", [super description], _x, _y];
}

So that you're not manually replicating the NSObject default and thereby blocking any non-default behaviour your superclass may have opted to include.

Beyond that, "summary string parsing error" is an lldb error. It's being reported by the debugger only. Per its documentation, po is correct for Objective-C objects; p is for C or C++ objects. So you needn't heed that error — it's essentially just telling you that you used the wrong lldb command.

EDIT: for what it's worth, the method used by CFArray is open source and looks like:

static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
    CFArrayRef array = (CFArrayRef)cf;
    CFMutableStringRef result;
    const CFArrayCallBacks *cb;
    CFAllocatorRef allocator;
    CFIndex idx, cnt;
    cnt = __CFArrayGetCount(array);
    allocator = CFGetAllocator(array);
    result = CFStringCreateMutable(allocator, 0);
    switch (__CFArrayGetType(array)) {
    case __kCFArrayImmutable:
    CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
    break;
    case __kCFArrayDeque:
    CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
    break;
    }
    cb = __CFArrayGetCallBacks(array);
    for (idx = 0; idx < cnt; idx++) {
    CFStringRef desc = NULL;
    const void *val = __CFArrayGetBucketAtIndex(array, idx)->_item;
    if (NULL != cb->copyDescription) {
        desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val);
    }
    if (NULL != desc) {
        CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, desc);
        CFRelease(desc);
    } else {
        CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, val);
    }
    }
    CFStringAppend(result, CFSTR(")}"));
    return result;
}

As with the other comments above, I'm willing to gamble that the answer is: Xcode's debugger isn't smart in any sense and definitely isn't smart enough to use the correct po means of getting an Objective-C description; if your object is an uninflected Objective-C object then the debugger isn't going to be able to figure it out.

like image 118
Tommy Avatar answered Oct 08 '22 17:10

Tommy