1

I am trying to add a condition to NSObject's description method where any object that responds to a method in an optional protocol (PrettyPrinter) will print the result from the protocol method instead of the normal NSObject's description. However, if the object being printer does not respond to the protocol then the description should return how it normally does.

My current attempt at doing this involves writing a category on NSObject that contains this protocol and the overridden description method. However, I am unaware of any way to call a category's un-overridden method.

-(NSString*)description
{
    if ([self respondsToSelector:@selector(prettyPrinter)]) {
        return self.prettyPrinter;
    }else{
        // Would Like to return normal description if does not respond to selector. But
        // can not call super description due to being a category instead of a subclass
        return [super description];
    }
}

Any ideas on ways that I can accomplish this would be greatly appreciated. Thanks!

UPDATE: With a little more searching, it would seem like this may be able to be accomplished through something called swizzling. However, current attempts at this have not yet been successful. Any advise on techniques to use swizzling to accomplish this goal would also be helpful.

Krejko
  • 901
  • 1
  • 9
  • 23
  • If IO understood you question.... You should never over-ride a method by Categorising. – Anoop Vaidya Apr 19 '13 at 18:13
  • would you have any other suggestions that would allow me to use the %@ operator while printing the description of my objects? – Krejko Apr 19 '13 at 18:18
  • As you must be knowing you cant print `object`. You need to reach to primitive types only then you print. So why not to use printf and its %d, %f, %s, %ld, %c etc etc – Anoop Vaidya Apr 19 '13 at 18:22
  • I am aware. My 'prettyPrinter' method formats my objects to be printer properly. However, right now I must explicitly call my prettyPrinter. I was hoping I would be able to automate this process so that my prettyPrinter methods were called automatically. – Krejko Apr 19 '13 at 18:24

2 Answers2

2

As you point out, this is possible with method swizzling. The runtime has functionality to exchange the implementation of two methods.

#import <objc/runtime.h>

@interface NSObject (PrettyPrinter)
- (NSString*) prettyPrinter;
@end

@implementation NSObject (PrettyPrinter)

// This is called when the category is being added
+ (void) load {
  Method method1 = class_getInstanceMethod(self, @selector(description));
  Method method2 = class_getInstanceMethod(self, @selector(swizzledDescription));

  // this is what switches the two methods
  method_exchangeImplementations(method1, method2);
}

// This is what will be executed in place of -description
- (NSString*) swizzledDescription {
  if( [self respondsToSelector:@selector(prettyPrinter)] ) {
    return [self prettyPrinter];
  }
  else {
    return [self swizzledDescription];
    // The above is not a recursive call, remember the implementation has
    //   been exchanged, this will really execute -description
  }
}

- (NSString*) prettyPrinter {
  return @"swizzled description";
}

@end

The -prettyPrinter method can be removed, in which case NSLog will return the value defined by -description.

Note that this will only swizzle -description, although NSLog might call other methods, such as NSArray's –descriptionWithLocale:

Dave FN
  • 652
  • 1
  • 14
  • 29
  • This is exactly the type of implementation I was thinking of but didn't find any solid examples of swizzling that connected all the dots for me. Thank you for providing an example. – Krejko Jul 11 '13 at 15:38
-1

if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.

Click Here To Read More!

Community
  • 1
  • 1
Burhanuddin Sunelwala
  • 5,318
  • 3
  • 25
  • 51