A category might need to do a little more to install itself into the
class system, we’ll show how in the next example. Here we will be extending
NSDateFormatter
.
A NSDateFormatter
has several build-in behaviors that are specified by NSDateFormatterBehavior10_0
or NSDateFormatterBehavior10_4
.
We’d like to extend this with a custom behavior MyDateFormatterBehavior
and
here is how to do it.
Create a subclass of NSDateFormatter
This will implement the desired behavior. How this is implemented is not
shown. Lets just assume it’s a class called MyDateFormatter
.
@interface MyDateFormatter : NSDateFormatter
...
Patch class into NSDateFormatter
NSDateFormatter has an extension mechanism in place called +mulleSetClass:forFormatterBehavior:
,
where we associate a custom class with the behavior.
We would like to do this ASAP, which is when our custom class gets loaded into
the runtime. +load
will have to be used, since no one will be calling our
class directly.
The only thing we need to advertise to the user is our new constant value
MyDateFormatterBehavior
in a header somewhere for the new behavior:
Now comes the bad news, which is: it can be tricky. The following implementation is correct, but you have to know why.
@implementation MyDateFormatter
+ (void) load
{
[NSDateFormatter mulleSetClass:self
forFormatterBehavior:MyDateFormatterBehavior];
}
@end
As long as you are not using any other Objective-C class except your own class
and its superclasses, your code is safe. But as soon you are using another
class, even just @"some constant string"
then you have to declare its usage
beforehand. This can be tricky, when class-clusters come into play, where you
may not even know the class (NSConstantString
in this case for instance).
Even worse, if you are messaging another class, this in turn may message other
classes. And that may be hard to predict and maintain.
Fortunately you can declare a dependency on libraries, which in most cases should be Foundation or some equivalent.
Adding
MULLE_OBJC_DEPENDS_ON_LIBRARY( Foundation);
before the +load
method definition will be sufficient in most cases.
See bla bla for in depth
Next
Now lets see how a category supports Plug And Play.