我是Objective C中的新手,虽然我有一些Java反射的背景。
在这里,我有一个经典的类方法 findAll ,可以从数据库中找到所有域对象。 Univers 类直接继承自 DomainObject
@interface DomainObject : NSObject
- (NSString *) execute : (NSString*) method withJson:(NSString*)json;
+ (NSString*)findAll: (NSString*)json;
@end
@implementation DomainObject
- (NSString *) execute: (NSString*) method withJson:(NSString*)json{
method = [NSString stringWithFormat:@"%@%@", method, @":"];
//method is 'findAll:'
NSString* result = [ self performSelector:
NSSelectorFromString(method) withObject:json];// Error here
return result;
}
@end
当findAll不是类方法(即-findAll声明)时代码工作,但现在我有错误:NSInvalidArgumentException - [Univers findAll:] 很明显,运行时正在寻找实例方法。
有什么想法找到我的班级方法吗?
答案 0 :(得分:5)
而不是打电话
NSString* result = [self performSelector:NSSelectorFromString(method) withObject:json];
你需要打电话
NSString* result = [[self class] performSelector:NSSelectorFromString(method) withObject:json];
用于类方法。
毕竟它是对象实例的类,它应该调用方法,而不是实例本身。
简短说明:NSObject
实现- (Class)class;
(不要误认为具有类似效果的+ (Class)class
,NSObject
也实现了!),它会返回你的Class对象实例对象。请记住,除了普通的实例对象之外,在Objective-C中,类也是实际的对象:类型为Class
的对象,即(与id
,NSObject
,...)
请参阅-class
方法here的文档。
SEL selector = NSSelectorFromString(method);
if ([[self class] respondsToSelector:selector]) {
NSString* result = [[self class] performSelector:selector withObject:json];
}
一般来说,Objective-C中的一个常见模式是通过[object class]
接收类对象来调用对象的类方法。
考虑这个名为Foo
的类的情况,它实现了一个方便的方法,用于返回自身的自动释放实例(通过:Foo *newFoo = [Foo foo];
调用):
虽然可以实现这样的方法(毕竟我们知道对象的类名,对吧?):
+ (id)foo {
return [[[Foo alloc] init] autorelease];
}
正确的方法是:
+ (id)foo {
return [[[self alloc] init] autorelease];
}
因为第一个会导致子类中的多态性问题(例如一个名为FooBar
的子类,它应该显然是[FooBar alloc] …
,而不是[Foo alloc] …
。幸运的是{{1} }动态解决这个问题。
虽然这显然不是彻底解释这个问题的正确场所(可能是人们可能会说的非常偏离),但是当然值得注意/警告,imho。