ios-runtime

 

git下載地址:git@github.com:lu459700780/RunTime.gitgit

viewController.hgithub

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController

@property(nonatomic,strong)NSString *hello;
@property(nonatomic,strong)NSString *hello1;

/**
 *  交換方法使用
 */
- (void)method1;
- (void)method2;

@end

viewController.m函數

#import "ViewController.h"
#import "RunTime.h"
#import "RunTime+Category.h"

//項目下載地址:git@github.com:lu459700780/RunTime.git
@interface ViewController ()

@end

@implementation ViewController

-(NSString *)description{
    return [NSString stringWithFormat:@"hello:%@",_hello];
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        _hello = @"hello";
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];
    _hello = @"hello";
    
    
    //獲取某一個類全部屬性和全部方法
    [RunTime getAllPropertyAndAllMethod:[ViewController class]];
    //改變某一屬性值
    [RunTime changeVariable];
    //增長新方法
    [RunTime addNewMethod];
    //交換方法
    [RunTime exchangeMethod];
    
    //增長新屬性
    RunTime *keytool = [[RunTime alloc]init];
    keytool.newVariable = @"Hello";
    keytool.height = 100;
    NSLog(@"%@",[keytool newVariable]);
    NSLog(@"%f",[keytool height]);

    
}


- (void)method1
{
    NSLog(@"method1");
}
- (void)method2
{
    NSLog(@"method2");
}


@end

RunTime.h編碼

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface RunTime : NSObject

/**
 *  獲取全部成員變量和方法
 *
 *  @param myClass 類別
 */
+ (void)getAllPropertyAndAllMethod:(id)myClass;

/**
 *  改變屬性值
 */
+ (void)changeVariable;
/**
 *  增長新方法
 */
+ (void)addNewMethod;
/**
 *  交換方法
 */
+ (void)exchangeMethod;



@end

RunTime.matom

#import "RunTime.h"
#import <objc/runtime.h>
#import "ViewController.h"
//獲取屏幕寬度的宏
#define ScreenWidth ([[UIScreen mainScreen] bounds].size.width)


@implementation RunTime

+ (void)getAllPropertyAndAllMethod:(id)myClass
{
    unsigned int outCount = 0;
    // 獲取到全部的成員變量列表
    Ivar *vars = class_copyIvarList([myClass class], &outCount);
    // 遍歷全部的成員變量
    for (int i = 0; i < outCount; i++) {
        Ivar ivar = vars[i]; // 取出第i個位置的成員變量
        
        const char *propertyName = ivar_getName(ivar); // 獲取變量名
        const char *propertyType = ivar_getTypeEncoding(ivar); // 獲取變量編碼類型
        printf("變量名%s/變量編碼類型%s\n", propertyName, propertyType);
       
    }
    
    unsigned int count;
    //獲取方法列表,全部在.m文件顯式實現的方法都會被找到,包括setter+getter方法;
    Method *allMethods = class_copyMethodList([myClass class], &count);
    for(int i =0;i<count;i++)
    {
        //Method,爲runtime聲明的一個宏,表示對一個方法的描述
        Method md = allMethods[i];
        //獲取SEL:SEL類型,即獲取方法選擇器@selector()
        SEL sel = method_getName(md);
        //獲得sel的方法名:以字符串格式獲取sel的name,也即@selector()中的方法名稱
        const char *methodname = sel_getName(sel);
        NSLog(@"(Method:%s)",methodname);
    }
    
    
}

+ (void)changeVariable
{
    ViewController *viewVC = [[ViewController alloc]init];
    NSLog(@"改變前的viewVC裏面的屬性:%@",viewVC);
    
    unsigned int count = 0;
    Ivar *vars = class_copyIvarList([ViewController class], &count);
    Ivar ivv = vars[0]; //從第一個方法getAllVariable中輸出的控制檯信息,咱們能夠看到實例屬性。
    object_setIvar(viewVC, ivv, @"world"); //屬性被強制改成world。
    
    NSLog(@"改變以後的viewVC裏面的屬性:%@",viewVC);
    
}

+ (void)addNewMethod
{
    /* 動態添加方法:
     第一個參數表示Class cls 類型;
     第二個參數表示待調用的方法名稱;
     第三個參數(IMP)addingMethod,IMP一個函數指針,這裏表示指定具體實現方法addingMethod;
     第四個參數表方法的參數,0表明沒有參數;
     */
    
    Method newMethod = class_getInstanceMethod(self, @selector(myNewMethod));
    
    ViewController *viewVC = [[ViewController alloc]init];
    
    class_addMethod([viewVC class], @selector(myNewMethod), method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
    //調用方法
    [viewVC performSelector:@selector(myNewMethod) withObject:nil];
}

- (void)myNewMethod
{
    
    NSLog(@"addNewMethod");
}
//具體的實現(方法的內部都默認包含兩個參數Class類和SEL方法,被稱爲隱式參數。)
int addingMethod(id self, SEL _cmd){
    NSLog(@"已新增方法:myNewMethod");
    
    return 1;
}

+ (void)exchangeMethod
{
    ViewController *viewVC = [[ViewController alloc]init];
    
    Method method1 = class_getInstanceMethod([viewVC class], @selector(method1));
    Method method2 = class_getInstanceMethod([viewVC class], @selector(method2));
    
    //交換方法
    method_exchangeImplementations(method1, method2);
    
    [viewVC method1];
}



@end

  RunTime+Category.hspa

#import "RunTime.h"
@interface RunTime (Category)


/**
 *  增長屬性(字符串類型)
 */
@property (nonatomic,strong)NSString *newVariable;
/**
 *  增長屬性(常量)
 */
@property (nonatomic,assign)float height;


@end

 

 RunTime+Category.m指針

#import "RunTime+Category.h"
#import <objc/runtime.h> //runtime API的使用須要包含此頭文件

//增長多個屬性,key值不能同樣
const char * keytool = "keytool"; //作爲key,字符常量 必須是C語言字符串;
const char * keytool2 = "keytool2"; //作爲key,字符常量 必須是C語言字符串;

@implementation RunTime (Category)

/**
 *  添加新屬性
 *
 *  @param newVariable 新屬性名
 */
-(void)setNewVariable:(NSString *)newVariable{
    
    NSString *newStr = [NSString stringWithFormat:@"%@",newVariable];
    /*
     第一個參數是須要添加屬性的對象;
     第二個參數是屬性的key;
     第三個參數是屬性的值;
     第四個參數是一個枚舉值,相似@property屬性建立時設置的關鍵字,可從命名看出各含義
     */
    objc_setAssociatedObject([RunTime class],keytool, newStr, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

/**
 *  提取屬性的值
 *
 *  @return 屬性值
 */
-(NSString *)newVariable{
    NSString *myNewVariable = objc_getAssociatedObject([RunTime class], keytool);
    return myNewVariable;
}

/**
 *  添加新屬性
 *
 *  @param height 新屬性名
 */
-(void)setHeight:(float)height{
    NSNumber *num = [NSNumber numberWithFloat:height];
    /*
     第一個參數是須要添加屬性的對象;
     第二個參數是屬性的key;
     第三個參數是屬性的值;
     第四個參數是一個枚舉值,相似@property屬性建立時設置的關鍵字,可從命名看出各含義
     */
    objc_setAssociatedObject([RunTime class],keytool2, num, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

/**
 *  提取屬性的值
 *
 *  @return 屬性值
 */
-(float)height{
    NSNumber *number = objc_getAssociatedObject([RunTime class], keytool2);
    return [number floatValue];
}

@end
相關文章
相關標籤/搜索