0

I'm tearing my hair out trying to do the simplest of tasks... subclassing an NSAttributedString. Trying to call the super class's initWithAttributedString: method is causing an unrecognized selector sent to instance error.

MODAttributedString.h:

#import <Foundation/Foundation.h>

@interface MODAttributedString : NSAttributedString

@property (nonatomic, retain) NSDictionary *links;

+ (MODAttributedString*) attributedStringWithFormat:(NSString*)text args:(id)argOne, ... NS_REQUIRES_NIL_TERMINATION;
+ (MODAttributedString*) attributedStringWithFormat:(NSString*)text attributes:(NSDictionary*)attributeDict;

@end

The code that is causing the crash (I'll explain the reason I split the alloc from the init in a moment):

MODAttributedString *modString = [MODAttributedString alloc];
// Pausing debugger here and typing 'po modString' causes gdb error
modString = [modString initWithAttributedString:attributedString];

My only clue is that stepping over the alloc call, when I try to po modString, I'm given this error:

"The program being debugged hit an ObjC exception while in a function called from gdb. If you don't want exception throws to interrupt functions called by gdb set objc-exceptions-interrupt-hand-call-fns to off. GDB has restored the context to what it was before the call. To change this behavior use "set unwindonsignal off" Evaluation of the expression containing the function (_NSPrintForDebugger) will be abandoned."

If I temporarily change the super class of MODAttributedString to a UIView, the alloc does not cause the gdb error (I stop the debugger prior to the init, which would obviously not work for anything other than an attributed string). However, common classes like NSArray, NSDictionary and NSAttributedString all fail with the same error.

In the method that calls the [MODAttributedString alloc] I use NSAttributedString as its own standalone class just fine. I am sure I'm including the MODAttributedString header in this .m file as well.

I'm using Xcode 4.2 and the iPhone 5 simulator. I've cleaned the project multiple times, tried creating a new project, tried using both LLVM GCC 4.2 and Apple LLVM 3.0, restarted Xcode and restarted my machine all to no success. I searched for this particular issue heavily before posting, but I only found issues related to properties, never to a superclass's public methods.

Is this a build settings issue? A configuration error? A compiler bug? I've subclassed common Apple classes hundreds of times, and for some reason this is the first time I've ever had an issue. Has anyone else ever had a similar problem? It's probably a really simple fix, but I just can't seem to figure it out on my own.

Thanks in advance!

brainfree
  • 817
  • 1
  • 8
  • 15

1 Answers1

3

It isn't "the simplest of things". You can't subclass NSAttributedString - it's part of a class cluster. This means (among other things) that the class returned when you instantiate is not necessarily the class you asked for. See What exactly is a so called "Class Cluster" in Objective-C?

It is possible, with great pain and difficulty, to subclass within a class cluster, but my advice is to write a wrapper class instead; you'll be much happier. Cocoa's dynamic redirection of unhandled methods makes this very easy.

Community
  • 1
  • 1
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    “You can't subclass NSAttributedString - it's part of a class cluster” Let’s be clear: Yes, you can, and there is nothing inherent in class clusters in general that prevents subclassing (you can only subclass the public classes of the cluster, of course). NSString and NSAttributedString are designed to allow subclassing so that you can use them as interfaces to custom backing storage. – Chris Page Mar 18 '13 at 09:00