RunTime 大神之路

// 今天來揭開神祕的Runtime機制的面紗。希望不侷限於會,最重要的是會用!!!!

先自己創建一個Dog 類

當然包含頭文件哈

#import <objc/runtime.h>

#import "TestRunTime-Swift.h"




- (void)viewDidLoad {

    [superviewDidLoad];

    ////////////////////////////改變方法的實現  //////////////////////////

    // 如果 msgSend(p1,s1)不能用配置settings enable ... objc_msgSend Calls  ---NO

//    objc_msgSend(self, @selector(askLog));

    

    Method m1 =class_getInstanceMethod(self.class,@selector(askLog));

    Method m2 =class_getInstanceMethod(self.class,@selector(answerLog));

    

    method_exchangeImplementations(m1, m2);//交換兩個方法的實現

    objc_msgSend(self,@selector(askLog));

    

    // swift 需要預編譯一次

    Animal * animal= [[Animalalloc]init];

    [animal eat];

    

    

    ////////////////////////////// 動態添加方法  //////////////////////////

        class_addMethod(animal.class,@selector(walk), (IMP)walk,"i@:");

    [animal performSelector:@selector(walk)];


    


//////////////////////////////////  訪問成員變量  //////////////////////////

    unsigned count =0;

    Ivar  * ivars =class_copyIvarList(animal.class, &count);

    

    for (int i =0; i < count; i ++) {

        

        // 保護指針指向的地址不被改變, s可以指向其他地址,但是 s[1] = "s";不行

        constchar * s = ivar_getName(ivars[i]);

        NSString * property = [NSStringstringWithCString:s encoding:NSUTF8StringEncoding];

        NSLog(@" property = %@", property);

        //kvo 賦值

        [animal setValue:@"tomLI"forKey:property];

    }

    

/////////////////  valueForKeyPath valueForKey的區別   ////////////////////////

    NSDictionary * dict =@{@"one":@"1",

                            @"two":@{@"three":@"23"}

                            };

    NSLog(@"value %@",[dictvalueForKeyPath:@"two.three"]);// 可以訪問到 23

    NSLog(@"value %@",[dictvalueForKey:@"two.three"]);   // 訪問不到 23

    NSLog(@"animal name = %@", animal.name);

    

    //  c 裏面的字符串定義。 cstr是一個指針

    char * cstr ="sfg";

    char cstrs[12] ="234abc";

    NSLog(@"cstr = %s = cstrs = %s",cstr, cstrs);

 

/**

 *  _cmdObjective-C的方法中表示當前方法的selector,正如同self表示當前方法調用的對象實例一樣。

 */

    NSLog(@"_cmd %@",NSStringFromSelector(_cmd));

    

    

/////////////////  動態添加屬性  ////////////////////////

    self.testName =@"這是動態添加的屬性";

    NSLog(@"testName = %@",self.testName);

    

}


void walk(idself, SEL_cmd){

    NSLog(@"給動物類添加走路的方法!!");

}


void add(idself, SEL_cmd){

    NSLog(@"這是動態添加方法!");

}



- (void)askLog

{

    NSLog(@"我是誰!!!");

}

- (void)answerLog

{

    NSLog(@"我是你大爺");

}



static charconst * testNameKey = "testNameKey";

- (void)setTestName:(NSString*)name

{

    /*

     OBJC_ASSOCIATION_ASSIGN;            //assign策略

     OBJC_ASSOCIATION_COPY_NONATOMIC;    //copy策略

     OBJC_ASSOCIATION_RETAIN_NONATOMIC;  // retain策略

     

     OBJC_ASSOCIATION_RETAIN;

     OBJC_ASSOCIATION_COPY;

     */

    /*

     * id object 給哪個對象的屬性賦值

     const void *key 屬性對應的key

     id value  設置屬性值爲value

     objc_AssociationPolicy policy  使用的策略,是一個枚舉值,和copyretainassign是一樣的,手機開發一般都選擇NONATOMIC

     objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

     */

    objc_setAssociatedObject(self,testNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);

}


- (NSString*)testName

{

    return (NSString*)objc_getAssociatedObject(self,testNameKey);

}


輸出:

2017-04-25 10:22:19.331 TestRunTime[2370:333381] 我是你大爺

2017-04-25 10:22:19.332 TestRunTime[2370:333381] 我在吃東西!

2017-04-25 10:22:19.332 TestRunTime[2370:333381] 給動物類添加走路的方法!!

2017-04-25 10:22:19.332 TestRunTime[2370:333381]  property = name

2017-04-25 10:22:19.333 TestRunTime[2370:333381] value 23

2017-04-25 10:22:19.333 TestRunTime[2370:333381] value (null)

2017-04-25 10:22:19.333 TestRunTime[2370:333381] animal name = tomLI

2017-04-25 10:22:19.333 TestRunTime[2370:333381] cstr = sfg = cstrs = 234abc

2017-04-25 10:22:19.333 TestRunTime[2370:333381] _cmd viewDidLoad

2017-04-25 10:22:19.333 TestRunTime[2370:333381] testName = 這是動態添加的屬性




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