如何调用我使用NSClassFromString动态创建的类中的方法?

时间:2011-02-05 22:01:15

标签: iphone objective-c xcode cocoa dynamic

我正在进行动态类加载的原因是因为我正在创建一组可以在多个类似项目中使用的文件,因此执行#import然后正常实例化将无法正常工作。动态类允许我这样做,只要我可以在这些类中调用方法。每个项目在pch中都有一个不同的“kMediaClassName”名称,所以我可以根据我所在的项目动态加载不同的类:

#define kMediaClassName @"Movie"

以下是我用来动态获取类实例的代码:

Class mediaClass = NSClassFromString(kMediaClassName);
id mediaObject = [[[mediaClass alloc] init] autorelease];

然后我尝试在该动态类中调用一个方法:

[mediaObject doSomething];

当我将其输入Xcode时,编译器会显示一个警告,即该类没有此方法,即使它有。我可以在我的Movie.h文件中看到它。到底是怎么回事?如何从动态实例化的类中调用方法?

如果我需要传递多个参数怎么办?

[mediaObject loadMedia:oneObject moveThe:YES moveA:NO];

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:8)

你可以声明一个协议,如下所示:

@protocol MONMediaProtocol

/*
  remember: when synthesizing the class, you may want
  to add the protocol to the synthesized class for your sanity
*/

- (BOOL)downloadMediaAtURL:(NSURL *)url toPath:(NSString *)path loadIfSuccessful:(BOOL)loadIfSuccessful;

/* ...the interface continues... */

@end

正在使用中:

Class mediaClass = NSClassFromString(kMediaClassName);
assert(mediaClass);

id<MONMediaProtocol> mediaObject = [[[mediaClass alloc] init] autorelease];
assert(mediaObject);

NSURL * url = /* expr */;
NSString * path = /* expr */;

BOOL loadIfSuccessful = YES;

BOOL success = [mediaObject downloadMediaAtURL:url toPath:path loadIfSuccessful:loadIfSuccessful];

答案 1 :(得分:2)

好吧它可能存在,但编译器不知道它,因为它假设mediaClass只是一些Class对象,但没有具体。 NSClassFromString()是一个运行时函数,因此无法在编译时向编译器提供有关该对象的提示。

你能做什么:

  • 忽略警告
  • 使用[media performSelector:@selector(doSomething)];

顺便说一句,这是错误的:

Class mediaClass; = NSClassFromString(kMediaClassName);

它应该是:

Class mediaClass = NSClassFromString(kMediaClassName);

答案 2 :(得分:1)

比NSInvocation 更简单,更漂亮的解决方案:)

Class mediaClass = NSClassFromString(kMediaClassName);
if(mediaClass){
    id mediaObject = class_createInstance(mediaClass,0);
    objc_msgSend(mediaObject, @selector(doSomethingWith:andWith:alsoWith:), firstP, secondP,thirdP);
}

<强>解释

class_createInstance(mediaClass,0);[[mediaClass alloc] init];完全相同 如果您需要自动发布,只需执行通常的[mediaObject autorelease];

objc_msgSend()performSelector:方法完全相同,但objc_msgSend()允许您根据需要添加任意数量的参数。那么,比NSInvocation更容易吗?顺便说一句,他们的签名是:

id class_createInstance(Class cls, size_t extraBytes)
id objc_msgSend(id theReceiver, SEL theSelector, ...)

有关详细信息,请参阅Objective-C Runtime Reference

答案 3 :(得分:0)

正如Joe Blow所说,NSInvocation将在这里为您提供帮助,尽管NSObject有几种可以使用的快捷方法:-performSelector:-performSelector:withObject:-performSelector:withObject:withObject:

相关问题