2011-02-05 25 views
3

我做動態類加載的原因是因爲我正在創建一組可用於多個類似項目的文件,因此執行#import然後正常實例化將不起作用。動態類允許我這樣做,只要我可以在這些類中調用方法。每個項目都有這與不同的「kMediaClassName」的名字PCH這樣我就可以動態加載基於項目我在不同的類別:如何在我使用NSClassFromString動態創建的類中調用方法?

#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]; 

感謝您的幫助提前。

回答

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]; 
2

那麼它可能在那裏,但編譯器不知道它,因爲它假定mediaClass只是一些Class對象,但沒有具體的。 NSClassFromString()是一個運行時函數,因此無法在編譯時向編譯器提供有關該對象的提示。

你可以做什麼:

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

而且順便說一句,這是錯誤的:

Class mediaClass; = NSClassFromString(kMediaClassName); 

它應該是:

Class mediaClass = NSClassFromString(kMediaClassName); 
+0

如果我需要多個參數傳遞給方法?例如:`[mediaObject loadMedia:oneObject moveThe:YES moveA:NO];` – 2011-02-05 22:13:55

+0

然後使用像Joe Blow這樣的NSInvocation已經提出,它是您在這種情況下最好的選擇。 – JustSid 2011-02-05 22:15:49

+0

您可以隨時使用objective-c運行時功能來完成該功能。請看我的答案:) – nacho4d 2011-02-05 23:00:51

0

正如Joe Blow所說,NSInvocation會幫助你,雖然NSObject有一些你可以使用的快捷方法:-performSelector:,-performSelector:withObject:-performSelector:withObject:withObject:

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

相關問題