我熟悉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发消息的方法?
答案 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);