runtime 基礎(chǔ)篇(一)

#import "DisplayAttribute.h"
#import <objc/runtime.h>

@implementation DisplayAttribute
/**
 *  必備常識(shí):
 *  Ivar : 成員變量    如果要是動(dòng)態(tài)創(chuàng)建/修改/查看屬性,可以使用Ivar
 *  Method : 成員方法  如果要是動(dòng)態(tài)創(chuàng)建/修改/查看方法,可以使用Method
 *  下面的例子教大家一些runtime簡(jiǎn)單的 查看類中屬性和方法以及動(dòng)態(tài)添加屬性和方法和修改屬性.
 */

/**
 *  通過(guò)類的名字來(lái)獲取類里面包含的所有屬性
 *
 *  @param className 類名(egs:UIView)
 */
- (void)getIvarsNameListWithClassName:(NSString *)className
{
    //通過(guò)類的名字獲取到類(egs:通過(guò)"學(xué)生"這個(gè)類的名字找到"學(xué)生"這個(gè)類)
    Class ClassName = NSClassFromString(className);
    
    //定義一個(gè)變量來(lái)存放遍歷出來(lái)類里面屬性的個(gè)數(shù)
    unsigned int outConut = 0;
    //查取類里面所有的屬性
    Ivar * vars = class_copyIvarList([ClassName class], &outConut);
    //打印類里面有多少個(gè)屬性
    NSLog(@"%d",outConut);
    
    //遍歷類里面所有的屬性 和 屬性類型
    for (int i = 0; i < outConut; i ++) {
        //獲取類里面屬性的名字(將IVar變量轉(zhuǎn)化為字符串)
        const char * ivarName = ivar_getName(vars[i]);
        //獲取類里面屬性的類型(獲取IVar的類型)
        const char * ivarType = ivar_getTypeEncoding(vars[i]);
        //打印屬性的名字和類型
        printf("屬性名字:%s 屬性類型:%s\n",ivarName,ivarType);
        
        /**
         *  如果你想對(duì)這個(gè)類動(dòng)態(tài)賦值修改的話,有兩種
         1:可以用KVC模式來(lái)進(jìn)行賦值修改.不管它有沒(méi)有在.h中聲明(只要類中有這個(gè)屬性),都可以賦值
         *  例如:類中有一個(gè)屬性為:"name",你這個(gè)時(shí)候就可以直接賦值了.
         *  [p1 setValue:@"東方_未明" forKey:@"name"];
         2:Ivar name = vars[1];//找到對(duì)應(yīng)的下表
         *  object_setIvar(p1, name, @"童星");
         *  可以打印查看有沒(méi)有修改成功
         *  NSLog(@"%@",[p1 valueForKey:@"name"]);
         */
    }
    /**
     *  動(dòng)態(tài)為類添加屬性
     */
    //通過(guò)類名獲取到的類,創(chuàng)建一個(gè)對(duì)象
    NSObject *p1 = [[[ClassName class] alloc] init];
    
    //給"p1"這個(gè)對(duì)象動(dòng)態(tài)添加一個(gè)屬性:Key: name Vaule:lishijie,
    static char name;
    objc_setAssociatedObject(p1, &name, @"東方_未明", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    //獲取"p1"這個(gè)對(duì)象屬性為"name"的lishijie
    NSString * strName = objc_getAssociatedObject(p1, &name);
    //打印動(dòng)態(tài)添加的屬性
    NSLog(@"我是動(dòng)態(tài)添加的屬性:%@",strName);
    
}

/**
 *  通過(guò)類的名字,查看類中所有的方法
 *
 *  @param className 類的名字(egs:UIView)
 */
- (void)getMethodNameListWithClassName:(NSString *)className
{
    //如果想添加方法直接調(diào)用就行了(只需要改一下類)
    //添加方法
    [self addMethod];
    /**
     * class_copyMethodList:獲取所有方法
     * method_getName:讀取一個(gè)Method類型的變量,輸出我們?cè)谏蠈又泻苁煜さ腟EL
     *
     */
    
    //通過(guò)類的名字,獲取到類
    Class ClassName = NSClassFromString(className);
    //定義一個(gè)變量來(lái)存放遍歷出來(lái)類里面屬性的個(gè)數(shù)
    unsigned int count = 0;
    //查取類里面所有的屬性
    Method * method = class_copyMethodList(ClassName, &count);
    //遍歷類里面所有的屬性 和 屬性類型
    for (int i = 0; i < count; i ++) {
        //獲取類里面方法的名字
        SEL methodName = method_getName(method[i]);
        //獲取類里面方法的類型
        const char * methodType = method_copyReturnType(method[i]);
        NSLog(@"方法名字:%@,方法類型:%s",NSStringFromSelector(methodName),methodType);
    }
    
    
}

/**
  class_addMethod的實(shí)現(xiàn)會(huì)覆蓋父類的方法實(shí)現(xiàn),但不會(huì)取代本類中已存在的實(shí)現(xiàn),
如果本類中包含一個(gè)同名的實(shí)現(xiàn),則函數(shù)會(huì)返回NO。

如果要修改已存在實(shí)現(xiàn),可以使用method_setImplementation。
一個(gè)Objective-C方法是一個(gè)簡(jiǎn)單的C函數(shù),它至少包含兩個(gè)參數(shù)—self和_cmd。
所以,我們的實(shí)現(xiàn)函數(shù)(IMP參數(shù)指向的函數(shù))至少需要兩個(gè)參數(shù)
*/

//添加方法
- (void)addMethod
{
    //例如: 給UIView添加一個(gè)方法
    
    //給類添加一個(gè)方法
    id p1 = [NSString new];
    /**
     *  IMP指向的兩個(gè)方法,必須實(shí)現(xiàn)(一個(gè)是函數(shù)的名字,一個(gè)是要實(shí)現(xiàn)的函數(shù))
     *
     *  @param class]               類
     *  @param @selectormethod1Name 函數(shù)的名字
     *  @param IMPmethod1           要實(shí)現(xiàn)的函數(shù)
     *  @param "v@"                 函數(shù)參數(shù)的類型
     *
     *  @return void
     *
     */
    class_addMethod([NSString class], @selector(method1Name), (IMP)method1, "v@");
    //調(diào)用方法1
    [p1 method1Name];
    
}

//------------------------添加方法需要實(shí)現(xiàn)的--------------------------//
//方法的名字,沒(méi)有實(shí)際的作用,只是標(biāo)識(shí)類里面有這個(gè)函數(shù)
- (void)method1Name
{
    NSLog(@"我只是個(gè)method1名字");
}


//這個(gè)才是方法的實(shí)現(xiàn)  (根據(jù)method1Name  找到  method1 這個(gè)方法)
static void method1(id self, SEL _cmd, int a){
    NSLog(@"我是動(dòng)態(tài)添加的method");
    
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • NSObject方法 Cocoa中大多數(shù)對(duì)象是繼承自NSObjectl類的子類(唯一例外的是NSProxy類)NS...
    水落斜陽(yáng)閱讀 447評(píng)論 0 1
  • Objective-C作為一門(mén)動(dòng)態(tài)編譯語(yǔ)言,會(huì)將編譯和連接時(shí)要做的事情推遲到運(yùn)行時(shí)。這代表著OC語(yǔ)言不僅僅需要一個(gè)...
    userName閱讀 522評(píng)論 0 50
  • 前言 2016年6月9號(hào)開(kāi)始Runtime NSObject方法 Cocoa中大多數(shù)對(duì)象是繼承自NSObjectl...
    js丶閱讀 1,437評(píng)論 0 5
  • 轉(zhuǎn)載標(biāo)哥的一篇博客, 寫(xiě)的真是詳細(xì) Method類型 Method類型是一個(gè)objc_method結(jié)構(gòu)體指針,而結(jié)...
    東方_未明閱讀 1,025評(píng)論 0 6
  • 每次都想自己寫(xiě), 但是時(shí)間太少, 最重要的是每次想寫(xiě), 都發(fā)現(xiàn)很多寫(xiě)的太好的文章, 找一個(gè)寫(xiě)的深入淺出的文章轉(zhuǎn)載一...
    東方_未明閱讀 258評(píng)論 0 1