在运行时向类添加Objective-C方法

8

我正在尝试在旧系统上支持10.9中新添加的NSColor方法。在10.9之前,我将它们放在一个类别中,这样可以统一Mac和iOS之间的代码。现在10.9有了这些方法,在使用它们时会出现奇怪的绘图问题。我想动态地将这些方法添加到旧的运行时中,我已经找到了几个使用class_addMethod的方法来实现。问题是,即使addMethod返回成功,这些方法也不会被调用。

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);
}

任何指针都将受到高度赞赏。
2个回答

6

class_addMethod()用于向类中添加实例方法。你正在尝试添加一个类方法,因此需要将该方法添加到元类(类是它们的元类的实例)。可以通过以该类作为参数调用object_getClass()来获取元类:

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

BOOL success = class_addMethod(metaclass, @selector(colorWithWhite:alpha:), (IMP)fColorWithWhite, "@@:ff");

没有成功。class_addMethod 返回 false。 - greg
哦,这里可以运行。你在测试哪个SDK?如果该方法已经存在(例如在10.9上),它将失败。 - jscs
我正在使用10.8进行构建,这样我就可以实际看到错误并且不会有代码支持。目前我没有一个低于10.9的系统来运行,所以在发布之前,这似乎是我成功测试的最佳选择。 - greg

6

您正在尝试添加类方法。您需要将它们添加到元类中。

Class meta_cls = objc_getMetaClass("NSColor");

这看起来非常惊人,我简直不敢相信我在API文档中没有看到它,但是在class_addMethod上也返回了false。 - greg
已解决:以上方法可行。根本问题与将double转换为CGFloat再转换为float有关。 - greg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接