如何获得 class 方法的选择器?
How to get a selector of a class method?
我有下一段代码,我在其中获取指向实例方法的指针:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
@end
@implementation TestClass
- (void)someMethod { // This is instance method, it's okay
NSLog(@"Hello from some method!");
}
@end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], @selector(someMethod));
someMethodImplementation();
return 0;
}
效果不错。但是如果我想得到一个指向 class 方法的指针,它是行不通的:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
@end
@implementation TestClass
+ (void)someMethod { // This is class method, it doesn't work
NSLog(@"Hello from some method!");
}
@end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], @selector(someMethod));
someMethodImplementation();
return 0;
}
它不起作用,因为它无法查找方法实现。
我确信它必须有效,因为如果我以这种方式获得实现它就有效:
MethodWithoutParams someMethodImplementation =
[TestClass methodForSelector:@selector(someMethod)];
所以我研究了 NSObject 实现并查看了下一个代码:
+ (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation((id)self, sel);
}
- (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation(self, sel);
}
还有object_getMethodImplementation()
函数has下一个实现:
IMP object_getMethodImplementation(id obj, SEL name)
{
Class cls = (obj ? obj->getIsa() : nil);
return class_getMethodImplementation(cls, name);
}
因此 class 方法查找和实例方法查找的实现是相同的。
但它不起作用,我不知道为什么。我想任何类型的方法(class 和实例)都将位于调度 table 中,我可以获得指向任何这些方法的指针。但是如你所见,我做不到。
您需要查询 class 的元class。 class 方法是其 metaclass.
上的实例方法
Class meta = objc_getMetaClass("TestClass");
SEL sel = @selector(someMethod);
typedef void (*MyMethodImplementation)(Class, SEL);
MyMethodImplementation someMethodImplementation = (MyMethodImplementation)class_getMethodImplementation(meta, sel);
someMethodImplementation([TestClass class], sel);
注意,方法(实例或 class)永远不会 "without parameters"。必须始终至少使用接收者(实例或 class)和选择器调用它。
我完全不知道 Objective-C 运行时。但这是我的咆哮:
object_getMethodImplementation 对于 class 方法:
// returns a class method implementation, can't find instance methods
class_getMethodImplementation([TestClass class]->getIsa(),
@selector(classMethod));
相当于
class_getMethodImplementation(objc_getMetaClass("TestClass"),
@selector(classMethod));
object_getMethodImplementation 例如方法:
// returns an instance method implementation, can't find class methods
class_getMethodImplementation((<TestClass instance>)->getIsa(),
@selector(someMethod));
相当于:
class_getMethodImplementation([TestClass class],
@selector(someMethod))
所以看起来 <TestClass instance>->getIsa()
returns 一个等于 [TestClass class]
returns 的指针。我猜你现在知道 class 方法中的 self
和实例方法中的 self
有什么区别了。
所以您应该按照@KenThomases 的建议使用元class。
我有下一段代码,我在其中获取指向实例方法的指针:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
@end
@implementation TestClass
- (void)someMethod { // This is instance method, it's okay
NSLog(@"Hello from some method!");
}
@end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], @selector(someMethod));
someMethodImplementation();
return 0;
}
效果不错。但是如果我想得到一个指向 class 方法的指针,它是行不通的:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
@end
@implementation TestClass
+ (void)someMethod { // This is class method, it doesn't work
NSLog(@"Hello from some method!");
}
@end
int main(int argc, const char * argv[]) {
typedef void (*MethodWithoutParams)();
MethodWithoutParams someMethodImplementation =
class_getMethodImplementation([TestClass class], @selector(someMethod));
someMethodImplementation();
return 0;
}
它不起作用,因为它无法查找方法实现。
我确信它必须有效,因为如果我以这种方式获得实现它就有效:
MethodWithoutParams someMethodImplementation =
[TestClass methodForSelector:@selector(someMethod)];
所以我研究了 NSObject 实现并查看了下一个代码:
+ (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation((id)self, sel);
}
- (IMP)methodForSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return object_getMethodImplementation(self, sel);
}
还有object_getMethodImplementation()
函数has下一个实现:
IMP object_getMethodImplementation(id obj, SEL name)
{
Class cls = (obj ? obj->getIsa() : nil);
return class_getMethodImplementation(cls, name);
}
因此 class 方法查找和实例方法查找的实现是相同的。
但它不起作用,我不知道为什么。我想任何类型的方法(class 和实例)都将位于调度 table 中,我可以获得指向任何这些方法的指针。但是如你所见,我做不到。
您需要查询 class 的元class。 class 方法是其 metaclass.
上的实例方法Class meta = objc_getMetaClass("TestClass");
SEL sel = @selector(someMethod);
typedef void (*MyMethodImplementation)(Class, SEL);
MyMethodImplementation someMethodImplementation = (MyMethodImplementation)class_getMethodImplementation(meta, sel);
someMethodImplementation([TestClass class], sel);
注意,方法(实例或 class)永远不会 "without parameters"。必须始终至少使用接收者(实例或 class)和选择器调用它。
我完全不知道 Objective-C 运行时。但这是我的咆哮:
object_getMethodImplementation 对于 class 方法:
// returns a class method implementation, can't find instance methods
class_getMethodImplementation([TestClass class]->getIsa(),
@selector(classMethod));
相当于
class_getMethodImplementation(objc_getMetaClass("TestClass"),
@selector(classMethod));
object_getMethodImplementation 例如方法:
// returns an instance method implementation, can't find class methods
class_getMethodImplementation((<TestClass instance>)->getIsa(),
@selector(someMethod));
相当于:
class_getMethodImplementation([TestClass class],
@selector(someMethod))
所以看起来 <TestClass instance>->getIsa()
returns 一个等于 [TestClass class]
returns 的指针。我猜你现在知道 class 方法中的 self
和实例方法中的 self
有什么区别了。
所以您应该按照@KenThomases 的建议使用元class。