5

I'm trying to understand the Objective-C runtime a little bit better. Consider NSAttributedString.h which has a minimal interface followed by a more extensive category NSExtendedAttributedString.

Now consider the following code:

NSAttributedString *attributedString = [[NSAttributedString alloc] initWithAttributedString:[[NSAttributedString alloc] initWithString:@"ABC"]];
NSLog(@"Result: %@", attributedString); 
NSLog(@"Exists? %@", [NSString stringWithUTF8String:sel_getName(method_getName(class_getInstanceMethod(NSAttributedString.class, @selector(initWithAttributedString:))))]);    
NSLog(@"Exists? %@", [NSString stringWithUTF8String:sel_getName(method_getName(class_getInstanceMethod(NSAttributedString.class, @selector(string))))]);

// Produces this output
2013-04-19 10:17:35.364 TestApp[53300:c07] Result: ABC{
}
2013-04-19 10:17:35.364 TestApp[53300:c07] Exists? <null selector>
2013-04-19 10:17:35.365 TestApp[53300:c07] Exists? string

We find the instance method that is part of the canonical interface, but not the one in the category. How can this happen and yet it can be successfully called? Is there a way to introspect and find the category method?

Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
Ben Flynn
  • 18,524
  • 20
  • 97
  • 142

1 Answers1

3

What happens in this case is that you assume attributedString to be of type NSAttributedString, which is not the case:

NSLog(@"Class: %@", [attributedString class]);

// Produces this output
2013-04-19 19:50:21.955 TestApp[1611:303] Class: NSConcreteAttributedString

If you change NSAttributedString.class in your code to [attributedString class] it will work as expected.

proxi
  • 1,243
  • 10
  • 18
  • But initWithAttributedString is a defined in a category of NSAttributedString, not of NSConcreteAttributedString. – Martin R Apr 19 '13 at 18:14
  • Good call and a good reminder to not expect that just because you alloc / init something you will get something of that class back. – Ben Flynn Apr 19 '13 at 18:15
  • 1
    I was aware that `initXXX` can return a different object, but here `[NSAttributedString alloc]` already returns an instance of `NSConcreteAttributedString`. I had not noticed this behavior before! – Martin R Apr 19 '13 at 19:49