Runtime相關(guān)方法

每個(gè)人的學(xué)習(xí)方式不同竖螃,我習(xí)慣于先了解每個(gè)方法的使用方式是什么记舆,方法是做什么用的。今天的runtime也是凳鬓。我們可以從官方文檔中找出runtime的所有方法


類相關(guān)的方法

在文檔中我們可以看到類相關(guān)的所有方法茁肠。


官方文檔runtime class相關(guān).gif

順便做個(gè)整理

class_get

class_get相關(guān).gif
  • (了解) class_getName (獲取類名) ,返回值類型const char *
 // 獲取類名 (獲取的是const char 類型數(shù)據(jù))
    NSLog(@"類名 :%s",class_getName([UILabel class]));

有點(diǎn)類似NSStringFromClass缩举,不過NSStringFromClass返回的是NSString

  • (了解) class_getSuperclass(獲取一個(gè)類的父類)垦梆,返回值類型class
// 獲取父類
    NSLog(@"父類 : %@",class_getSuperclass([UILabel class]));

NSObject里提供了一個(gè)superclass的只讀屬性,也可以獲取父類蚁孔。

  • (了解) class_getProperty ,(獲取指定的屬性)奶赔,返回值類型objc_property類型結(jié)構(gòu)體
objc_property_t property = class_getProperty([UILabel class], "text");
     // 打印一下獲取的屬性是什么 ,通過property_getName
NSString *propertyString = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
NSLog(@"取出的屬性 = %@",propertyString);
  • (了解)class_getVersion,(獲取版本號(hào)),返回值類型int
NSLog(@"版本號(hào) = %d", class_getVersion([UILabel class]));
  • (了解)class_getImageName,(獲取類坐在的動(dòng)態(tài)庫位置),返回類型const char *
NSLog(@"獲取類坐在的動(dòng)態(tài)庫位置 = %s", class_getImageName([UILabel class]));
  • (重要)class_getClassMethod杠氢,(獲取類方法)站刑,返回類型Method
Method method = class_getClassMethod([UILabel class], @selector(userInterfaceLayoutDirectionForSemanticContentAttribute:));
NSLog(@"方法名 = %s",sel_getName(method_getName(method)));
  • (重要)class_getInstanceMethod,(獲取實(shí)例方法)鼻百,返回類型Method
 Method instanceMethod = class_getInstanceMethod([UILabel class], @selector(setBackgroundColor:));
NSLog(@"實(shí)例方法名 = %s",sel_getName(method_getName(instanceMethod)));
  • (了解)class_getClassVariable绞旅,(獲取類的成員變量信息)摆尝,返回類型Ivar
Ivar ivar = class_getClassVariable([Person class], "_sex");
  • (重要)class_getMethodImplementation,(獲取實(shí)例方法)因悲,返回類型IMP
IMP imp = class_getMethodImplementation([UILabel class], @selector(setBackgroundColor:));
  • (了解)class_getInstanceSize堕汞,(獲取實(shí)例對(duì)象大小),返回類型size_t
size_t size = class_getInstanceSize([UILabel class]);
    NSLog(@"實(shí)例對(duì)象大小 = %li",size);
  • (了解)class_getIvarLayout([UILabel class]) class_getWeakIvarLayout([UILabel class])晃琳,(獲取類的成員變量信息)讯检,返回類型const uint8_t *可以參考這篇

  • 輸出

2018-08-02 18:36:31.060785+0800 runtime[27722:927392] 類名 :UILabel
2018-08-02 18:36:31.060988+0800 runtime[27722:927392] 類名 :UILabel
2018-08-02 18:36:31.061228+0800 runtime[27722:927392] 父類 : UIView
2018-08-02 18:36:31.064525+0800 runtime[27722:927392] 取出的屬性 = text
2018-08-02 18:36:31.064713+0800 runtime[27722:927392] 版本號(hào) = 0
2018-08-02 18:36:31.064841+0800 runtime[27722:927392] 獲取類坐在的動(dòng)態(tài)庫位置 = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/UIKit.framework/UIKit
2018-08-02 18:36:31.064974+0800 runtime[27722:927392] 方法名 = userInterfaceLayoutDirectionForSemanticContentAttribute:
2018-08-02 18:36:31.065233+0800 runtime[27722:927392] 實(shí)例方法名 = setBackgroundColor:
2018-08-02 18:36:31.065715+0800 runtime[27722:927392] 實(shí)例對(duì)象大小 = 728

class_copy

class_copy相關(guān).gif
  • (重要)class_copyIvarList卫旱,(獲取類的實(shí)例變量列表)人灼,返回類型Ivar *
    獲取類的實(shí)例變量列表
unsigned int count = 0;
Ivar * varList = class_copyIvarList([UILabel class], &count);;
for (int i = 0; i<count; i++) {
     NSLog(@"%s",ivar_getName(varList[i]));
}
 //釋放varList
free(varList);
  • (重要)class_copyMethodList,(獲取類的所有方法)顾翼,返回類型Method *
    獲取類的所有方法
unsigned int count = 0;
    Method *method = class_copyMethodList([UILabel class], &count);;
    for (int i = 0; i<count; i++) {
        NSLog(@"%s",sel_getName(method_getName(method[i])));
    }
//釋放varList
    free(method);
  • (重要)class_copyPropertyList投放,(獲取類的屬性列表),返回類型objc_property_t *
    獲取屬性列表
unsigned int count = 0;
objc_property_t *property = class_copyPropertyList([UILabel class], &count);;
    for (int i = 0; i<count; i++) {
        NSLog(@"%s",property_getName(property[i]));
    }
    //釋放varList
    free(property);
  • (重要)class_copyProtocolList适贸,(獲取類的協(xié)議列表)灸芳,返回類型Protocol * __unsafe_unretained *
Protocol * __unsafe_unretained *protocol = class_copyProtocolList([UITableViewController class], &count);;
    for (int i = 0; i<count; i++) {
        Protocol *pro = protocol[I];
        NSLog(@"%@",NSStringFromProtocol(pro));
    }
    //釋放varList
    free(protocol);

因?yàn)樯厦娴膸讉€(gè)方法打印的東西太長,就不輸出了拜姿。

class_add

class_add相關(guān).gif
  • (了解)class_addIvar烙样,(為類動(dòng)態(tài)添加實(shí)例變量),返回類型BOOL
class_addIvar([Person class], "addLength", sizeof(NSInteger), log2(_Alignof(NSInteger)), @encode(NSInteger));
  • (重要)class_addMethod砾隅,(為類動(dòng)態(tài)添加方法)误阻,返回類型BOOL
    這里說重要注意是因?yàn)閙ethod swizzle
// 取得函數(shù)名稱
    SEL originSel = @selector(setText:);
    SEL swizzleSel = @selector(swizzleSetText:);
    Method originMethod = class_getInstanceMethod(class, originSel);
    Method swizzleMethod = class_getInstanceMethod(class, swizzleSel);

// 添加方法
    BOOL addMethod = class_addMethod(class, originSel, method_getImplementation(swizzleMethod),method_getTypeEncoding(swizzleMethod));
  • (了解)class_addProperty债蜜,(為類動(dòng)態(tài)添加屬性)晴埂,返回類型BOOL
    我們開發(fā)中一般用關(guān)聯(lián)對(duì)象添加屬性。
objc_property_attribute_t type = { "T", "@\"NSString\"" };//屬性類型為NSString
    objc_property_attribute_t ownership = { "C", "copy" }; // C = copy
    objc_property_attribute_t backingivar  = { "V", "_personName" };
    objc_property_attribute_t attrs[] = { type, ownership, backingivar };
    class_addProperty([Person class], "personName", attrs, 3);
  • (了解)class_addProtocol寻定,(為類動(dòng)態(tài)添加屬性)儒洛,返回類型BOOL
class_addProtocol(<#Class  _Nullable __unsafe_unretained cls#>, <#Protocol * _Nonnull protocol#>)

class_replace

class_replace相關(guān).gif
  • (重要)class_replaceMethod,(為類替換方法)
class_replaceMethod(class, swizzleSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
  • (了解)class_replaceProperty狼速,(替換類的屬性)
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );

class_conformsTo

class_ conform相關(guān).gif
  • (了解)class_conformsToProtocol,(類是否實(shí)現(xiàn)指定的協(xié)議) 琅锻,返回值類型(BOOL)
 class_conformsToProtocol ( Class cls, Protocol *protocol );

實(shí)際開發(fā)我們一般用NSObject的- (BOOL)conformsToProtocol:(Protocol *)aProtocol;方法。

class_respondsTo

class_respond相關(guān).gif
  • (了解)** class_respondsToSelector**,(是否可以響應(yīng)方法) 向胡,返回值類型(BOOL)
class_respondsToSelector(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull sel#>)

實(shí)際開發(fā)我們一般用NSObject的- (BOOL)respondsToSelector:(SEL)aSelector;方法恼蓬。


objc_ 和 object_

  • objc_ 所有方法


    官方文檔runtime objc_相關(guān).gif
  • object_所有方法


    屏幕快照 2018-08-03 下午3.01.26.png

objc_get

屏幕快照 2018-08-03 下午1.56.53.png
  • (重要)objc_getClass,(獲取對(duì)象的類) ,返回值類型 Class
NSLog(@"%@",objc_getClass("Person"));

輸出

2018-08-03 15:26:46.212256+0800 runtime[30988:1216350] Person

在實(shí)際開發(fā)中我們一般用NSClassFromString()來通過類名獲取一個(gè)類

  • (重要)object_getClass,(獲取一個(gè)類isa指針指向的類) 僵芹,返回值類型 Class
    4τ病!拇派!注意這個(gè)方法要和上面區(qū)分開荷辕,這是用來獲取isa指針指向的類凿跳,如果不知道isa指針的同學(xué)自己去百度
Class metaClass = object_getClass([Person class]);
NSLog(@"%@", class_isMetaClass(metaClass) ? @"是元類" : @"不是元類");
NSLog(@"%@", class_isMetaClass([Person class]) ? @"是元類" : @"不是元類");
    
NSLog(@"Person類的isa指向%@",object_getClass([Person class]));
NSLog(@"Person元類的isa指向%@",object_getClass(object_getClass([Person class])));
NSLog(@"NSObject元類的isa指向%@",object_getClass(object_getClass(object_getClass([Person class]))));
NSLog(@"NSObject元類的父類 = %@",class_getSuperclass(object_getClass(object_getClass([Person class]))));
NSLog(@"NSObject元類的父類的父類 = %@",class_getSuperclass(class_getSuperclass(object_getClass(object_getClass([Person class])))));

輸出

2018-08-03 16:00:14.819770+0800 runtime[31283:1243260] 是元類
2018-08-03 16:00:14.819992+0800 runtime[31283:1243260] 不是元類
2018-08-03 16:00:14.820157+0800 runtime[31283:1243260] Person類的isa指向Person
2018-08-03 16:00:14.820287+0800 runtime[31283:1243260] Person元類的isa指向NSObject
2018-08-03 16:00:14.820417+0800 runtime[31283:1243260] NSObject元類的isa指向NSObject
2018-08-03 16:00:14.820518+0800 runtime[31283:1243260] NSObject元類的父類 = NSObject
2018-08-03 16:00:14.820645+0800 runtime[31283:1243260] NSObject元類的父類的父類 = (null)

我們可以看出 object_getClass方法是獲取一個(gè)類的元類,Person類的isa指針指向Person元類,Person元類的isa指針指向NSObject元類疮方,NSObject元類的isa指向自己控嗜,形成了一個(gè)閉環(huán)。并且NSObject元類的父類是NSObject骡显,NSObject的父類為null
是不是想起了一張圖

449095-3e972ec16703c54d.png

  • (了解)objc_getMetaClass,(獲取類的元類) 疆栏,返回值類型Class *
  • (了解)object_getClassName,(獲取類的元類名稱) ,返回值類型const char *

區(qū)別于object_getClass獲取元類惫谤,objc_getMetaClass獲取元類用的是c字符串承边。既然object_getClass是獲取一個(gè)對(duì)象的元類對(duì)象,那么object_getClassName一個(gè)猜想的出來是獲取元類對(duì)象的名稱石挂。

NSLog(@"Person類的元類 = %@",objc_getMetaClass("Person"));
NSLog(@"Person元類的元類的名稱 = %s",object_getClassName(objc_getMetaClass("Person")));
NSLog(@"Person元類的isa指針指向 = %@",objc_getMetaClass(object_getClassName(objc_getMetaClass("Person"))));

輸出

2018-08-03 16:14:49.051873+0800 runtime[31357:1254499] Person類的isa指針 = Person
2018-08-03 16:14:49.052081+0800 runtime[31357:1254499] Person元類名稱 = NSObject
2018-08-03 16:14:49.052217+0800 runtime[31357:1254499] Person元類的isa指針指向 = NSObject
  • (了解)objc_getProtocol,(獲取一個(gè)協(xié)議) 博助,返回值類型Protocol *
Protocol *protocol =  objc_getProtocol("PersonDelegate");

這個(gè)在實(shí)際開發(fā)中就是@protocol(PersonDelegate)

  • (了解)objc_getClassList,(獲取類列表)
    我們可以用這個(gè)方法來打印一個(gè)類所有的子類
int numClasses = 0, newNumClasses = objc_getClassList(NULL, 0);
    Class *classes = NULL;
    while (numClasses < newNumClasses) {
        numClasses = newNumClasses;
        classes = (Class *)realloc(classes, sizeof(Class) * numClasses);
        newNumClasses = objc_getClassList(classes, numClasses);
        
        for (int i = 0; i < numClasses; i++) {
            const char *className = class_getName(classes[i]);
            if (class_getSuperclass(classes[i]) == [UILabel class]) {
                NSLog(@"%s" , className);
            }
        }
        
    }
    free(classes);

輸出UILabel的所有子類對(duì)象。

2018-08-03 16:45:45.430312+0800 runtime[31498:1276113] _MKUILabel
2018-08-03 16:45:45.430450+0800 runtime[31498:1276113] _UITableViewHeaderFooterViewLabel
2018-08-03 16:45:45.430567+0800 runtime[31498:1276113] _UIActivityGroupActivityCellTitleLabel
2018-08-03 16:45:45.430899+0800 runtime[31498:1276113] UITabBarButtonLabel
2018-08-03 16:45:45.431003+0800 runtime[31498:1276113] UITableViewLabel
2018-08-03 16:45:45.431205+0800 runtime[31498:1276113] UITextFieldLabel
2018-08-03 16:45:45.431304+0800 runtime[31498:1276113] UIButtonLabel
2018-08-03 16:45:45.431396+0800 runtime[31498:1276113] UIDateLabel
2018-08-03 16:45:45.431498+0800 runtime[31498:1276113] UITextLabel
2018-08-03 16:45:45.431594+0800 runtime[31498:1276113] UISegmentLabel
  • (了解)objc_getRequiredClass,(返回一個(gè)類痹愚,要是沒有這個(gè)類就去除這個(gè)類 ) 富岳,返回值類型Protocol *
    !!! 要設(shè)置Build Phase——》Compile Sources相應(yīng)文件ARC轉(zhuǎn)非ARC-fno-objc-arc;才能支持objc_getRequiredClass

  • (重要)objc_getAssociatedObject,(關(guān)聯(lián)對(duì)象get) 拯腮,返回值類型Protocol *

- (UILabel *)badge {
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setBadge:(UILabel *)label {
    objc_setAssociatedObject(self, @selector(badge), label, OBJC_ASSOCIATION_RETAIN);
}

這里個(gè)人喜歡用@selector()即當(dāng)前方法選擇子來代替關(guān)鍵字窖式。

  • (了解)object_getIvar,(獲取實(shí)例變量的值) ,返回值類型id*
_person = [[Person alloc] init];
 _person.name = @"小妹";
// 獲取_person實(shí)例對(duì)象中的name實(shí)例變量的值
NSString *name = object_getIvar(_person, class_getInstanceVariable([Person class], "_name"));
NSLog(@"name = %@",name);

輸出

2018-08-03 17:51:48.294600+0800 runtime[33733:1321519] name = 小妹

objc_copy

  • (了解)objc_copyClassList 动壤,返回值類型Class _Nonnull *萝喘。
    獲得已經(jīng)注冊(cè)的所有的類,下面打印UIScrollView的所有子類琼懊。
unsigned int outCount;
    Class *classes = objc_copyClassList(&outCount);
    for (int i = 0; i < outCount; i++) {
        @autoreleasepool {
            if (class_getSuperclass(classes[i]) == [UIScrollView class]) {
                NSLog(@"%s",class_getName(classes[i]));
            }
        }
    }
    free(classes);

輸出

2018-08-05 19:32:34.376451+0800 runtime[37322:1424135] _MKPlacePhotoView
2018-08-05 19:32:34.376782+0800 runtime[37322:1424135] NUIContentScrollView
2018-08-05 19:32:34.376940+0800 runtime[37322:1424135] _UIInterfaceActionRepresentationsSequenceView
2018-08-05 19:32:34.377093+0800 runtime[37322:1424135] _UIQueuingScrollView
2018-08-05 19:32:34.377196+0800 runtime[37322:1424135] _UIAlertControllerShadowedScrollView
2018-08-05 19:32:34.377307+0800 runtime[37322:1424135] _UICompatibilityTextView
2018-08-05 19:32:34.377404+0800 runtime[37322:1424135] UIPrinterSetupPINScrollView
2018-08-05 19:32:34.377599+0800 runtime[37322:1424135] UITextView
2018-08-05 19:32:34.377743+0800 runtime[37322:1424135] UIWebOverflowScrollView
2018-08-05 19:32:34.377845+0800 runtime[37322:1424135] UIPageControllerScrollView
2018-08-05 19:32:34.378044+0800 runtime[37322:1424135] UIWebScrollView
2018-08-05 19:32:34.378150+0800 runtime[37322:1424135] UIFieldEditor
2018-08-05 19:32:34.378248+0800 runtime[37322:1424135] UITableView
2018-08-05 19:32:34.378335+0800 runtime[37322:1424135] UITableViewWrapperView
2018-08-05 19:32:34.378437+0800 runtime[37322:1424135] UICollectionView
  • (了解)objc_copyImageNames,(獲取所有加載的Objective-C框架和動(dòng)態(tài)庫的名稱) 阁簸,返回值類型const char * _Nonnull *

  • (了解)objc_copyProtocolList,(獲取運(yùn)行時(shí)所知道的所有協(xié)議的數(shù)組) ,返回值類型Protocol * __unsafe_unretained _Nonnull *

  • (了解)objc_copyClassNamesForImage,(獲取指定庫或框架中所有類的類名) 哼丈,返回值類型const char * _Nonnull *

unsigned int outCount;
    const char ** classes = objc_copyClassNamesForImage(class_getImageName(NSClassFromString(@"UIView")), &outCount);
    for (int i = 0; i < outCount; i++) {
        NSLog(@"class name: %s", classes[i]);
    }
    free(classes);

objc_set

  • (重要)objc_setAssociatedObject,(設(shè)置關(guān)聯(lián)對(duì)象)
 objc_setAssociatedObject(id  _Nonnull object, //關(guān)聯(lián)對(duì)象
                             const void * _Nonnull key, // 關(guān)聯(lián)對(duì)象標(biāo)識(shí)符key启妹,我通常用@selector()作為標(biāo)識(shí)符
                             id  _Nullable value, // 關(guān)聯(lián)對(duì)象的值
                             objc_AssociationPolicy policy) // 關(guān)聯(lián)對(duì)象的內(nèi)存管理語義
  1. objc_AssociationPolicy是一個(gè)枚舉
    OBJC_ASSOCIATION_ASSIGN 等價(jià)于 @property(assign)。
    OBJC_ASSOCIATION_RETAIN_NONATOMIC等價(jià)于 @property(strong, nonatomic)醉旦。
    OBJC_ASSOCIATION_COPY_NONATOMIC等價(jià)于@property(copy, nonatomic)饶米。
    OBJC_ASSOCIATION_RETAIN等價(jià)于@property(strong,atomic)。
    OBJC_ASSOCIATION_COPY等價(jià)于@property(copy, atomic)

object_set

  • (重要)object_setIvar,(設(shè)置實(shí)例變量的值)
_person = [[Person alloc] init];
_person.name = @"小妹";
object_setIvar(_person, class_getInstanceVariable([Person class], "_name"),@"新名字");
NSLog(@"name = %@",_person.name);

輸出

2018-08-05 20:29:36.249324+0800 runtime[37441:1457957] name = 新名字
  • (重要)object_setClass,(設(shè)置對(duì)象的isa指向)
    !!! 類對(duì)象中存儲(chǔ)著實(shí)例對(duì)象的實(shí)例方法车胡,元類對(duì)象中存儲(chǔ)著類的類方法檬输。如果改變isa指向,會(huì)導(dǎo)致本來是對(duì)A類的方法緩存或方法列表中查找Method匈棘,變成從B類中查找Method丧慈。
@interface Person : NSObject
// 在Person .h文件中,有eat方法
- (void)eat:(NSString *)foodName;

@end

@implementation Person

- (instancetype)init {
    if (self = [super init]) {
 // 改變isa指針指向Animal類
        object_setClass(self, [Animal class]);
    }
    return self;
}

// 人吃食物
- (void)eat:(NSString *)foodName {
    NSLog(@"人吃食物 : %@",foodName);
}

@end
@interface Animal : NSObject

- (void)eat:(NSString *)foodName;

@end

@implementation Animal

- (void)eat:(NSString *)foodName {
    NSLog(@"動(dòng)物吃食物 : %@",foodName);
}

@end

調(diào)用方法

_person = [[Person alloc] init];
[_person eat:@"香蕉"];

輸出

2018-08-05 20:38:18.353851+0800 runtime[37495:1465311] 動(dòng)物吃食物 : 香蕉

所以真正調(diào)用方法的類并不一定是代碼中調(diào)用方法的那個(gè)類羹饰,最終和運(yùn)行時(shí)對(duì)象的isa指向有關(guān)伊滋。

  • (了解)object_setIvarWithStrongDefault,(設(shè)置實(shí)例變量的值)
_person = [[Person alloc] init];
_person.name = @"小妹";
object_setIvarWithStrongDefault(_person, class_getInstanceVariable([Person class], "_name"),@"新名字");
NSLog(@"name = %@",_person.name);
輸出
2018-08-05 20:53:05.701262+0800 runtime[37528:1475141] name = 新名字

創(chuàng)建銷毀類

  • (重要)** objc_allocateClassPair**,(創(chuàng)建一個(gè)類)
  • (重要)** objc_registerClassPair**,(注冊(cè)一個(gè)類)
  • (重要)** objc_disposeClassPair**,(銷毀一個(gè)類)
    runtime能在運(yùn)行時(shí)動(dòng)態(tài)添加一個(gè)類
 // 創(chuàng)建一個(gè)類
    Class newClass =  objc_allocateClassPair([Person class], "Man", 0);
     // 方法
    Method method = class_getInstanceMethod([self class], @selector(buyClothes));
     // 為類添加一個(gè)方法
    class_addMethod(newClass, method_getName(method), method_getImplementation(method), method_getTypeEncoding(method));
     // 注冊(cè)類
    objc_registerClassPair(newClass);
     // 創(chuàng)建類的實(shí)例對(duì)象 alloc
   id newInstance = class_createInstance(newClass, sizeof(unsigned));
     // init
   id hangzhouMan = [newInstance init];
     // 調(diào)用方法
   [hangzhouMan performSelector:@selector(buyClothes) withObject:nil];

創(chuàng)建類并調(diào)用方法碳却,輸出

2018-08-05 21:21:43.576871+0800 runtime[37627:1495822] 男人買衣服

銷毀

objc_disposeClassPair(newClass);
  // 調(diào)用方法
[hangzhouMan performSelector:@selector(buyClothes) withObject:nil]

銷毀之后調(diào)用方法,出現(xiàn)EXC_BAD_ACCESS


ivar(實(shí)例變量)

先看看ivar在底層的數(shù)據(jù)結(jié)構(gòu)

typedef struct objc_ivar *Ivar;

struct objc_ivar {
    char *ivar_name                 OBJC2_UNAVAILABLE;  // 變量名
    char *ivar_type                 OBJC2_UNAVAILABLE;  // 變量類型
    int ivar_offset                 OBJC2_UNAVAILABLE;  // 基地址偏移字節(jié)
#ifdef __LP64__
    int space                       OBJC2_UNAVAILABLE;
#endif
}

所有我們就能知道ivar通過runtime能獲得的變量

  • (重要)ivar_getName,(獲取實(shí)例變量名) 笑旺,返回值類型const char *
  • (重要)ivar_getOffset,(獲取實(shí)例基地址偏移字節(jié)) 昼浦,返回值類型int
  • (重要)ivar_getTypeEncoding,(獲取實(shí)例變量類型) ,返回值類型const char *
    結(jié)合上面介紹的
  • class_addIvar 筒主,(添加一個(gè)實(shí)例變量)
  • class_getInstanceVariable 关噪,(獲取實(shí)例變量)
  • object_setIvarWithStrongDefault ,(為實(shí)例變量賦值)
  • object_setIvar 乌妙,(為實(shí)例變量賦值)
  • object_getIvar 使兔,(獲取實(shí)例變量的值)
  • class_copyIvarList ,(獲取類的實(shí)例變量列表)

我來創(chuàng)建一個(gè)類藤韵,并在類中添加實(shí)例變量虐沥,賦值并打印。

  // 創(chuàng)建一個(gè)類newClass繼承Person
    Class newClass =  objc_allocateClassPair([Person class], "Man", 0);
     // 添加實(shí)例變量_skinColor
    BOOL flag1 = class_addIvar(newClass, "_skinColor", sizeof(NSString*), log2(sizeof(NSString *)), @encode(NSString *));
    if (flag1) {
        NSLog(@"NSString*類型  _skinColor變量添加成功");
    }
     // 注冊(cè)這個(gè)類
    objc_registerClassPair(newClass);
     // 獲取類的實(shí)例變量_skinColor
    Ivar colorIvar = class_getInstanceVariable(newClass, "_skinColor");
     // 創(chuàng)建實(shí)例對(duì)象instance
    id instance = [class_createInstance(newClass, sizeof(unsigned)) init];
     // 為這個(gè)實(shí)例對(duì)象的_skinColor賦值為黃色
    object_setIvar(instance, colorIvar, @"黃色");
     // 打印
    NSLog(@"膚色skinColor = %@",object_getIvar(instance, colorIvar));
    
     // 打印實(shí)例變量列表
    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList(newClass, &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        NSLog(@"實(shí)例變量name = %s",ivar_getName(ivar));
        NSLog(@"實(shí)例變量變量類型type = %s",ivar_getTypeEncoding(ivar));
        NSLog(@"實(shí)例變量地址偏移name = %td",ivar_getOffset(ivar));
    }

輸出

2018-08-06 10:43:30.631866+0800 runtime[42814:1664021] NSString*類型  _skinColor變量添加成功
2018-08-06 10:43:30.632097+0800 runtime[42814:1664021] 膚色skinColor = 黃色
2018-08-06 10:43:30.632235+0800 runtime[42814:1664021] 實(shí)例變量name = _skinColor
2018-08-06 10:43:30.632406+0800 runtime[42814:1664021] 實(shí)例變量變量類型type = @
2018-08-06 10:43:30.632506+0800 runtime[42814:1664021] 實(shí)例變量地址偏移name = 32

Method

先看看Method在底層的數(shù)據(jù)結(jié)構(gòu)

typedef struct objc_method *Method;

struct objc_method {
    SEL method_name                 OBJC2_UNAVAILABLE;  // 方法名
    char *method_types                  OBJC2_UNAVAILABLE; // 參數(shù)類型
    IMP method_imp                      OBJC2_UNAVAILABLE;  // 方法實(shí)現(xiàn)
}

所有我們就能知道Method通過runtime能獲得的變量

Method method = class_getInstanceMethod([self class], @selector(buyClothes));
NSLog(@"name = %s",sel_getName(method_getName(method)));
 NSLog(@"TypeEncoding = %s",method_getTypeEncoding(method));
NSLog(@"參數(shù)個(gè)數(shù) = %u",method_getNumberOfArguments(method));
IMP imp = method_getImplementation(method);

輸出

2018-08-06 18:50:56.227579+0800 runtime[46116:1950929] name = buyClothes
2018-08-06 18:50:56.227773+0800 runtime[46116:1950929] TypeEncoding = v16@0:8
2018-08-06 18:50:56.227903+0800 runtime[46116:1950929] 參數(shù)個(gè)數(shù) = 2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末泽艘,一起剝皮案震驚了整個(gè)濱河市欲险,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匹涮,老刑警劉巖天试,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異然低,居然都是意外死亡喜每,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門雳攘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來带兜,“玉大人,你說我怎么就攤上這事来农⌒妫” “怎么了崇堰?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵沃于,是天一觀的道長。 經(jīng)常有香客問我海诲,道長繁莹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任特幔,我火速辦了婚禮咨演,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚯斯。我一直安慰自己薄风,他們只是感情好饵较,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著遭赂,像睡著了一般循诉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撇他,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天茄猫,我揣著相機(jī)與錄音,去河邊找鬼困肩。 笑死划纽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锌畸。 我是一名探鬼主播勇劣,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼潭枣!你這毒婦竟也來了芭毙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤卸耘,失蹤者是張志新(化名)和其女友劉穎退敦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚣抗,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侈百,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了翰铡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钝域。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锭魔,靈堂內(nèi)的尸體忽然破棺而出例证,到底是詐尸還是另有隱情,我是刑警寧澤迷捧,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布织咧,位于F島的核電站,受9級(jí)特大地震影響漠秋,放射性物質(zhì)發(fā)生泄漏笙蒙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一庆锦、第九天 我趴在偏房一處隱蔽的房頂上張望捅位。 院中可真熱鬧,春花似錦、人聲如沸艇搀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焰雕。三九已至姜胖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淀散,已是汗流浹背右莱。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留档插,地道東北人慢蜓。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像郭膛,于是被迫代替她去往敵國和親晨抡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉则剃,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,725評(píng)論 0 9
  • 官方源碼下載地址:http://download.csdn.net/detail/liangliang103377...
    有一種再見叫青春閱讀 1,978評(píng)論 2 11
  • Objective-C語言是一門動(dòng)態(tài)語言耘柱,他將很多靜態(tài)語言在編譯和鏈接時(shí)期做的事情放到了運(yùn)行時(shí)來處理。這種動(dòng)態(tài)語言...
    tigger丨閱讀 1,404評(píng)論 0 8
  • objc_getAssociatedObject返回與給定鍵的特定對(duì)象關(guān)聯(lián)的值棍现。ID objc_getAssoci...
    有一種再見叫青春閱讀 1,583評(píng)論 0 7
  • 你是否總有莫名奇妙的煩躁调煎, 心情很糟糕,面對(duì)生活壓力總得不到釋放己肮,郁悶士袄、壓抑、想哭 谎僻。有時(shí)候想想人就是這樣吧娄柳。
    呂曉六閱讀 296評(píng)論 0 0