Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding Objective-C method to class at runtime

Tags:

objective-c

I'm trying to support newly added methods of NSColor in 10.9 on older systems. Pre-10.9 I had these in a category which allowed my to unify code between Mac and iOS. Now that 10.9 has these methods, I get odd drawing wherever I use them. I want to add these methods dynamically to older runtimes and I've found several references for how to do it using class_addMethod. The problem is, that even though addMethod returns success, the methods aren't called.

NSColor *
fColorWithWhite(id self, SEL _cmd, float white, float alpha) {
    return [NSColor colorWithDeviceWhite: white
                                   alpha: alpha];
}

NSColor *
fColorWithRedGreenBlue(id self, SEL _cmd, float red, float green, float blue, float alpha) {
    return [NSColor colorWithDeviceRed: red
                                 green: green
                                  blue: blue
                                 alpha: alpha];
}

+ (void)addLegacySupport {
    Class class = NSClassFromString(@"NSColor");

    BOOL success = class_addMethod(class, @selector(colorWithWhite:alpha:), (IMP)fColorWithWhite, "@@:ff");
    NSLog(@"colorWithWhite:alpha: - %i", success);

    success = class_addMethod(class, @selector(colorWithRed:green:blue:alpha:), (IMP)fColorWithRedGreenBlue, "@@:ffff");
    NSLog(@"colorWithRed:green:blue:alpha: - %i", success);
}

Any pointers would be much appreciated.

like image 664
greg Avatar asked Dec 23 '13 01:12

greg


2 Answers

You are trying to add class methods. You need to add them to the metaclass.

Class meta_cls = objc_getMetaClass("NSColor");
like image 60
Léo Natan Avatar answered Oct 24 '22 01:10

Léo Natan


class_addMethod() adds an instance method to the class. You are trying to add a class method. Thus, you need to add the method to the metaclass (classes are instances of their metaclasses), which you can get by calling object_getClass() with the class as the argument:

Class metaclass = object_getClass(NSClassFromString(@"NSColor"));

BOOL success = class_addMethod(metaclass, @selector(colorWithWhite:alpha:), (IMP)fColorWithWhite, "@@:ff");
like image 6
jscs Avatar answered Oct 24 '22 00:10

jscs