IOS 動態創建類Class

【Objective-C Runtime動態加載】---動態創建類Class

動態創建類Class,動態添加Class成員變量與成員函數,動態變量賦值與取值,動態函數調用等方法

a.使用objc_allocateClassPair創建一個類Class
    const char * className = "Calculator";
    Class kclass = objc_getClass(className);
    if (!kclass) 
    {
       Class superClass = [NSObject class]; 
       kclass = objc_allocateClassPair(superClass, className, 0);
    }

b.使用class_addIvar添加一個成員變量
    NSUInteger size;
    NSUInteger alignment;
    NSGetSizeAndAlignment("*", &size, &alignment);
    class_addIvar(kclass, "expression", size, alignment, "*");


    注:
    1.type定義參考:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
    2."*"星號代表字符(),iOS字符爲4位,並採用4位對齊kclass

c.使用class_addMethod添加成員方法
    class_addMethod(kclass, @selector(setExpressionFormula:), (IMP)setExpressionFormula, "v@:@");
    class_addMethod(kclass, @selector(getExpressionFormula), (IMP)getExpressionFormula, "@@:");

    static void setExpressionFormula(id self, SEL cmd, id value)
    {
       NSLog(@"call setExpressionFormula");
    }

    static void getExpressionFormula(id self, SEL cmd)
    {
        NSLog(@"call getExpressionFormula");
    } 

    注:
    1.type定義參考:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
    2."v@:@",解釋v-返回值void類型,@-self指針id類型,:-SEL指針SEL類型,@-函數第一個參數爲id類型
    3."@@:",解釋@-返回值id類型,@-self指針id類型,:-SEL指針SEL類型,
d.註冊到運行時環境
    objc_registerClassPair(kclass);
e.實例化類
    id instance = [[kclass alloc] init];
f.給變量賦值
   object_setInstanceVariable(instance, "expression", "1+1"); 
g.獲取變量值
    void * value = NULL;
    object_getInstanceVariable(instance, "expression", &value); 
h.調用函數

    [instance performSelector:@selector(getExpressionFormula)];

Runtime-動態創建類添加屬性和方法

  1. - (void)createClass  
  2. {  
  3.     Class MyClass = objc_allocateClassPair([NSObject class], "myclass"0);  
  4.     //添加一個NSString的變量,第四個參數是對其方式,第五個參數是參數類型  
  5.     if (class_addIvar(MyClass, "itest"sizeof(NSString *), 0"@")) {  
  6.         NSLog(@"add ivar success");  
  7.     }  
  8.     //myclasstest是已經實現的函數,"v@:"這種寫法見參數類型連接  
  9.     class_addMethod(MyClass, @selector(myclasstest:), (IMP)myclasstest, "v@:");  
  10.     //註冊這個類到runtime系統中就可以使用他了  
  11.     objc_registerClassPair(MyClass);  
  12.     //生成了一個實例化對象  
  13.     id myobj = [[MyClass alloc] init];  
  14.     NSString *str = @"asdb";  
  15.     //給剛剛添加的變量賦值  
  16.     //    object_setInstanceVariable(myobj, "itest", (void *)&str);在ARC下不允許使用  
  17.     [myobj setValue:str forKey:@"itest"];  
  18.     //調用myclasstest方法,也就是給myobj這個接受者發送myclasstest這個消息  
  19.     [myobj myclasstest:10];  
  20.   
  21. }  
  22. //這個方法實際上沒有被調用,但是必須實現否則不會調用下面的方法  
  23. - (void)myclasstest:(int)a  
  24. {  
  25.       
  26. }  
  27. //調用的是這個方法  
  28. static void myclasstest(id selfSEL _cmd, int a) //self和_cmd是必須的,在之後可以隨意添加其他參數  
  29. {  
  30.       
  31.     Ivar v = class_getInstanceVariable([self class], "itest");  
  32.     //返回名爲itest的ivar的變量的值  
  33.     id o = object_getIvar(self, v);  
  34.     //成功打印出結果  
  35.     NSLog(@"%@", o);  
  36.     NSLog(@"int a is %d", a);  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章