標籤:objectc反射機制 oc動態調用
和java一樣,Object-C也提供了反射的機制。
每一個類都有一個Class,擷取Class有以下三種方法。
// insert code here... //通過字串擷取class Class clazz = NSClassFromString(@"NSString"); NSLog(@"clazz的類型是%@",clazz); //直接用calzz 來建立對象 id str = [[clazz alloc] init]; //通過對象來擷取class NSLog(@"%@",[str class]); //通過類來擷取class NSLog(@"%d",clazz==NSString.class); NSLog(@"Hello, World!");
/**
2015-04-28 17:03:18.907 反射[1322:303] clazz的類型是NSString
2015-04-28 17:03:19.279 反射[1322:303] __NSCFConstantString
2015-04-28 17:03:19.280 反射[1322:303] 1
2015-04-28 17:03:19.281 反射[1322:303] Hello, World!
Program ended with exit code: 0
列印出來的結果是這樣,_NSString只是類簇的前端而已
**/
對與第一種和第二種方式,都是根據類擷取Class對象,比較之下,第一種代碼安全性更高,程式再編譯階段就可以檢測所需要訪問的Class是否存在。效能更高,因為無需調用方法。
動態調用的方法如下。直接上代碼
#import <Foundation/Foundation.h>@interface JQCar : NSObject@end
#import "JQCar.h"#import <objc/message.h>@implementation JQCar- (void)move:(NSNumber*)count{ int num = [count intValue]; for (int i=0; i<num; i++) { NSLog(@"%@",[NSString stringWithFormat:@"汽車正在路上行走%d",i]); }}- (double)addSpeed:(double)factor{ //動態調用move方法 //使用performSelector動態調用move方法 [self performSelector:@selector(move:) withObject:[NSNumber numberWithInt:2]]; [self performSelector:NSSelectorFromString(@"move:") withObject:[NSNumber numberWithInt:2]]; //使用objc_msgSend()函數動態調用 objc_msgSend(self,@selector(move:),[NSNumber numberWithInt:2]); objc_msgSend(self, NSSelectorFromString(@"move:"),[NSNumber numberWithInt:3]); NSLog(@"正在加速%g",factor); return 100*factor;}@end使用objc_msgSend可能報錯
//objc_msgSend()報錯Too many arguments to function call ,expected 0,have3
解決方案
//Build Setting--> Apple LLVM 6.0 - Preprocessing--> Enable Strict Checking of objc_msgSend Calls 改為 NO
#import <Foundation/Foundation.h>#import <objc/message.h>#import "JQCar.h"int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... //擷取JQCar類 Class clazz = NSClassFromString(@"JQCar"); //動態建立car id car = [[clazz alloc] init]; //使用performSelector方法來動態調用 [car performSelector:@selector(addSpeed:) withObject:[NSNumber numberWithLong:2]]; //使用Objec_send來動態調用 objc_send(car,@selector(addSpeed:),3.4); //定義函數指標變數 double (*addSpeed)(id ,SEL,double); //擷取car對象的addSpeed方法,再把addSpeed方法賦值給addSpeed指標變數 addSpeed = (double (*)(id,SEL,double))[car methodForSelector:NSSelectorFromString(@"addSpeed:")]; //調用addSpeed double speed = addSpeed(car, @selector(addSpeed:), 3.4); NSLog(@"加速後的速度是%g",speed); NSLog(@"Hello, World!"); } return 0;}
IOS開發反射和動態調用總結