将字符串转换为“方法” - 在类方法调用中使用

时间:2013-12-17 12:42:29

标签: objective-c nsstring selector

我熟悉NSSelectorFromString函数,我们可以使用该函数从字符串创建新的SEL

问题在于我无法使用它来执行类方法调用,因为performSelector方法仅适用于实例作为其接收方。

我需要一些可能有这样功能的东西:

NSString* colorName = colorsArray[num];
NSString* methodName = [NSString stringWithFormat:@"%@Color", colorName]; //will create blueColor or redColor, etc...
SEL colorMethod = NSSelectorFromString(methodName);
self.view.backgroundColor = [UIColor performSelector:colorMethod]; //this is not valid... since NSObject only has performSelector as an Instance method...

是否有另一种方法来保存表示可以作为类方法运行的方法的on-the-run变量,并且可以从NSString创建?

或者使用选择器向Class发消息的方法?

4 个答案:

答案 0 :(得分:2)

  

问题是我不能用它来执行类方法调用   因为performSelector方法仅适用于实例   接收机。

这是错误的。是什么让你认为UIColor类对象不是“实例”?类对象是对象,这意味着它们是某个类的“实例”。类对象是其根类的(某些子类)的实例,在UIColor的情况下是NSObject。 (换句话说,UIColor类对象也是NSObject并支持所有NSObject实例方法。)

如果你想了解它是如何工作的,那么每个类对象都是一个元类的实例。每个类都有自己的元类,并且元类在它们的类之后具有继承(即,如果A是B的超类,那么A的元类是B的元类的超类)。最后,根类的元类继承自根类本身(因此NSObject的元类继承自NSObject)。这意味着继承了类方法,而且根类(在本例中为NSObject)的实例方法由具有该根类的所有类继承为类方法。

答案 1 :(得分:1)

只需在类

上调用performSelector
#import <Foundation/Foundation.h>

@interface T : NSObject
+ (NSString*)foo;
+ (NSString*)redColor;
@end

@implementation T
+ (NSString*)foo {
    return @"bar";
}
+ (NSString*)redColor {
    return @"RED";
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        id tclass = [T class];
        NSLog(@"%@", [tclass performSelector:@selector(foo)]);
        NSLog(@"%@", [tclass performSelector:@selector(redColor)]);

        SEL sel = NSSelectorFromString(@"redColor");
        NSLog(@"%@", [tclass performSelector:sel]);

    }
}

答案 2 :(得分:0)

来自Cocoa Fundamentals Guide(已过时但此部分仍然有效):

  

运行时系统处理根类中定义的方法   特别的方式。可以执行根类中定义的实例方法   实例和类对象。因此,所有类对象   可以访问根类中定义的实例方法。

Foundation框架提供了两个根类:NSObject和NSProxy。 NSObject有一个记为– performSelector:的方法,但因为它是一个根类,所以任何子类都可以将它用作类方法。例如:+[UIColor performSelector:]-[UIColor performSelector:]都有效。运行时级别的解释是在newacct的答案中。

一个调用类方法,另一个调用实例方法。例如:

#import <Foundation/Foundation.h>

@interface A : NSObject
@end

@implementation A
+(void) x { NSLog(@"class method"); }
-(void) x { NSLog(@"instance method"); }
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        [A performSelector:@selector(x)];
        [[A new] performSelector:@selector(x)];
    }
}

打印

class method
instance method

答案 3 :(得分:0)

您还可以使用NSInvocation:

SEL sel = NSSelectorFromString(@"whiteColor");
NSMethodSignature *sig = [UIColor methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:sel];
[invocation setTarget:[UIColor class]];
CFTypeRef retVal;
[invocation invoke];
[invocation getReturnValue:&retVal];
NSLog(@"retVal: %@", retVal);